Codebase list pyhamcrest / ad706aa
Imported Upstream version 1.8.0 SVN-Git Migration 8 years ago
171 changed file(s) with 3379 addition(s) and 5342 deletion(s). Raw diff Collapse all Expand all
0 Full documentation: http://packages.python.org/PyHamcrest
1 Latest package: http://pypi.python.org/pypi/PyHamcrest
2 Latest sources: https://github.com/jonreid/PyHamcrest
3 Hamcrest information: http://code.google.com/p/hamcrest
0 === Version 1.8 ==
41
5 See also:
6 Objective-C version for Cocoa and iOS: https://github.com/jonreid/OCHamcrest
7 Quality Coding - Tools, tips and techniques for building quality in to your iOS programs: http://jonreid.blogs.com/qualitycoding/
2 * Supported versions
3 - Support for Python 2.5 and Jython 2.5 has been dropped. They may still work, but no promises.
4
5 * Bug Fixes
6 - [#39] is_empty was missing from the global namespace
7
8 * New Features
9 - Support for numpy numeric values in iscloseto (Alexander Beedie)
10 - A matcher targeting exceptions and call results (Per Fagrell)
11
12 === Version 1.7 ==
13
14 2 Sep 2013 (Version 1.7.2)
15 * Supported versions
16 - As of this version, support for Python 3.1 has been dropped due to no available CI platform.
17 - Added support for Python 3.3
18
19 * Bug fixes:
20 - string_contains_in_order is now used in the test as it would be in an application, and is properly exported. (Romilly Cocking)
21 - Fix mismatch description of containing_inanyorder (David Keijser)
22 - added import of stringmatches to text/__init__.py (Eric Scheidemantle)
23 - added matches_regexp to __all__ list to library/__init__.py (Eric Scheidemantle)
24
25 5 Jan 2010 (Version 1.7.1)
26 * Bug fixes:
27 - included a fix by jaimegildesagredo for issue #28 (has_properties was not importable)
28 - included a fix by keys for contains_inanyorder
29
30 29 Dec 2012
31 (All changes by Chris Rose unless otherwise noted.)
32
33 * New matchers:
34 - matches_regexp matches a regular expression in a string.
35 - has_properties matches an object with more than one property.
36 - is_empty matches any object with length 0.
37
38 * Improvements:
39 - Can now do matching against old-style classes.
40 - Sequence matchers handle generators, as well as actual sequences and
41 pseudo-sequences.
42 - README enhancements by ming13
843
944
1045 === Version 1.6 ==
+165
-132
PKG-INFO less more
00 Metadata-Version: 1.1
11 Name: PyHamcrest
2 Version: 1.6
2 Version: 1.8.0
33 Summary: Hamcrest framework for matcher objects
4 Home-page: http://code.google.com/p/hamcrest/
5 Author: Jon Reid
6 Author-email: jon.reid@mac.com
4 Home-page: https://github.com/hamcrest/PyHamcrest
5 Author: Chris Rose
6 Author-email: offline@offby1.net
77 License: New BSD
8 Download-URL: http://pypi.python.org/packages/source/P/PyHamcrest/PyHamcrest-1.6.tar.gz
9 Description: * [Full documentation](http://packages.python.org/PyHamcrest)
10 * [Latest package](http://pypi.python.org/pypi/PyHamcrest)
11 * [Latest sources](https://github.com/jonreid/PyHamcrest)
12 * [Hamcrest information](http://code.google.com/p/hamcrest)
13
14 See also:
15
16 * [OCHamcrest](https://github.com/jonreid/OCHamcrest) - Objective-C version for
17 Cocoa and iOS.
18 * [Quality Coding](http://jonreid.blogs.com/qualitycoding/) - Tools, tips and
19 techniques for _building quality in_ to your iOS programs.
20
8 Download-URL: http://pypi.python.org/packages/source/P/PyHamcrest/PyHamcrest-1.8.0.tar.gz
9 Description: PyHamcrest
10 ==========
11
12 .. image:: https://pypip.in/v/PyHamcrest/badge.png
13 :alt: Release Status
14 :target: https://crate.io/packages/PyHamcrest
15 .. image:: https://pypip.in/d/PyHamcrest/badge.png
16 :alt: Downloads
17 :target: https://crate.io/packages/PyHamcrest
18 .. image:: https://travis-ci.org/hamcrest/PyHamcrest.png?branch=master
19 :alt: Build Status
20 :target: https://travis-ci.org/hamcrest/PyHamcrest
2121
2222 Introduction
2323 ============
5050
5151 We'll start by writing a very simple PyUnit test, but instead of using PyUnit's
5252 ``assertEqual`` method, we'll use PyHamcrest's ``assert_that`` construct and
53 the standard set of matchers::
54
55 from hamcrest import *
56 import unittest
57
58 class BiscuitTest(unittest.TestCase):
59 def testEquals(self):
60 theBiscuit = Biscuit('Ginger')
61 myBiscuit = Biscuit('Ginger')
62 assert_that(theBiscuit, equal_to(myBiscuit))
63
64 if __name__ == '__main__':
65 unittest.main()
53 the standard set of matchers:
54
55 .. code:: python
56
57 from hamcrest import *
58 import unittest
59
60 class BiscuitTest(unittest.TestCase):
61 def testEquals(self):
62 theBiscuit = Biscuit('Ginger')
63 myBiscuit = Biscuit('Ginger')
64 assert_that(theBiscuit, equal_to(myBiscuit))
65
66 if __name__ == '__main__':
67 unittest.main()
6668
6769 The ``assert_that`` function is a stylized sentence for making a test
6870 assertion. In this example, the subject of the assertion is the object
7274 since the ``Biscuit`` class defines an ``__eq__`` method.
7375
7476 If you have more than one assertion in your test you can include an identifier
75 for the tested value in the assertion::
76
77 assert_that(theBiscuit.getChocolateChipCount(), equal_to(10), 'chocolate chips')
78 assert_that(theBiscuit.getHazelnutCount(), equal_to(3), 'hazelnuts')
79
80 As a convenience, assert_that can also be used to verify a boolean condition::
81
82 assert_that(theBiscuit.isCooked(), 'cooked')
77 for the tested value in the assertion:
78
79 .. code:: python
80
81 assert_that(theBiscuit.getChocolateChipCount(), equal_to(10), 'chocolate chips')
82 assert_that(theBiscuit.getHazelnutCount(), equal_to(3), 'hazelnuts')
83
84 As a convenience, assert_that can also be used to verify a boolean condition:
85
86 .. code:: python
87
88 assert_that(theBiscuit.isCooked(), 'cooked')
8389
8490 This is equivalent to the ``assert_`` method of unittest.TestCase, but because
8591 it's a standalone function, it offers greater flexibility in test writing.
9298
9399 * Object
94100
95 * ``equal_to`` - match equal object
96 * ``has_length`` - match ``len()``
97 * ``has_property`` - match value of property with given name
98 * ``has_string`` - match ``str()``
99 * ``instance_of`` - match object type
100 * ``none``, ``not_none`` - match ``None``, or not ``None``
101 * ``same_instance`` - match same object
101 * ``equal_to`` - match equal object
102 * ``has_length`` - match ``len()``
103 * ``has_property`` - match value of property with given name
104 * ``has_properties`` - match an object that has all of the given properties.
105 * ``has_string`` - match ``str()``
106 * ``instance_of`` - match object type
107 * ``none``, ``not_none`` - match ``None``, or not ``None``
108 * ``same_instance`` - match same object
102109
103110 * Number
104111
105 * ``close_to`` - match number close to a given value
106 * ``greater_than``, ``greater_than_or_equal_to``, ``less_than``,
107 ``less_than_or_equal_to`` - match numeric ordering
112 * ``close_to`` - match number close to a given value
113 * ``greater_than``, ``greater_than_or_equal_to``, ``less_than``,
114 ``less_than_or_equal_to`` - match numeric ordering
108115
109116 * Text
110117
111 * ``contains_string`` - match part of a string
112 * ``ends_with`` - match the end of a string
113 * ``equal_to_ignoring_case`` - match the complete string but ignore case
114 * ``equal_to_ignoring_whitespace`` - match the complete string but ignore
115 extra whitespace
116 * ``starts_with`` - match the beginning of a string
117 * ``string_contains_in_order`` - match parts of a string, in relative order
118 * ``contains_string`` - match part of a string
119 * ``ends_with`` - match the end of a string
120 * ``equal_to_ignoring_case`` - match the complete string but ignore case
121 * ``equal_to_ignoring_whitespace`` - match the complete string but ignore extra whitespace
122 * ``matches_regexp`` - match a regular expression in a string
123 * ``starts_with`` - match the beginning of a string
124 * ``string_contains_in_order`` - match parts of a string, in relative order
118125
119126 * Logical
120127
121 * ``all_of`` - ``and`` together all matchers
122 * ``any_of`` - ``or`` together all matchers
123 * ``anything`` - match anything, useful in composite matchers when you don't
124 care about a particular value
125 * ``is_not`` - negate the matcher
128 * ``all_of`` - ``and`` together all matchers
129 * ``any_of`` - ``or`` together all matchers
130 * ``anything`` - match anything, useful in composite matchers when you don't care about a particular value
131 * ``is_not`` - negate the matcher
126132
127133 * Sequence
128134
129 * ``contains`` - exactly match the entire sequence
130 * ``contains_inanyorder`` - match the entire sequence, but in any order
131 * ``has_item`` - match if given item appears in the sequence
132 * ``has_items`` - match if all given items appear in the sequence, in any
133 order
134 * ``is_in`` - match if item appears in the given sequence
135 * ``only_contains`` - match if sequence's items appear in given list
135 * ``contains`` - exactly match the entire sequence
136 * ``contains_inanyorder`` - match the entire sequence, but in any order
137 * ``has_item`` - match if given item appears in the sequence
138 * ``has_items`` - match if all given items appear in the sequence, in any order
139 * ``is_in`` - match if item appears in the given sequence
140 * ``only_contains`` - match if sequence's items appear in given list
136141
137142 * Dictionary
138143
139 * ``has_entries`` - match dictionary with list of key-value pairs
140 * ``has_entry`` - match dictionary containing a key-value pair
141 * ``has_key`` - match dictionary with a key
142 * ``has_value`` - match dictionary with a value
144 * ``has_entries`` - match dictionary with list of key-value pairs
145 * ``has_entry`` - match dictionary containing a key-value pair
146 * ``has_key`` - match dictionary with a key
147 * ``has_value`` - match dictionary with a value
143148
144149 * Decorator
145150
146 * ``described_as`` - give the matcher a custom failure description
147 * ``is_`` - decorator to improve readability - see `Syntactic sugar` below
151 * ``calling`` - wrap a callable in a deffered object, for subsequent matching on calling behaviour
152 * ``raises`` - Ensure that a deferred callable raises as expected
153 * ``described_as`` - give the matcher a custom failure description
154 * ``is_`` - decorator to improve readability - see `Syntactic sugar` below
148155
149156 The arguments for many of these matchers accept not just a matching value, but
150157 another matcher, so matchers can be composed for greater flexibility. For
157164
158165 PyHamcrest strives to make your tests as readable as possible. For example, the
159166 ``is_`` matcher is a wrapper that doesn't add any extra behavior to the
160 underlying matcher. The following assertions are all equivalent::
161
162 assert_that(theBiscuit, equal_to(myBiscuit))
163 assert_that(theBiscuit, is_(equal_to(myBiscuit)))
164 assert_that(theBiscuit, is_(myBiscuit))
167 underlying matcher. The following assertions are all equivalent:
168
169 .. code:: python
170
171 assert_that(theBiscuit, equal_to(myBiscuit))
172 assert_that(theBiscuit, is_(equal_to(myBiscuit)))
173 assert_that(theBiscuit, is_(myBiscuit))
165174
166175 The last form is allowed since ``is_(value)`` wraps most non-matcher arguments
167176 with ``equal_to``. But if the argument is a type, it is wrapped with
168 ``instance_of``, so the following are also equivalent::
169
170 assert_that(theBiscuit, instance_of(Biscuit))
171 assert_that(theBiscuit, is_(instance_of(Biscuit)))
172 assert_that(theBiscuit, is_(Biscuit))
177 ``instance_of``, so the following are also equivalent:
178
179 .. code:: python
180
181 assert_that(theBiscuit, instance_of(Biscuit))
182 assert_that(theBiscuit, is_(instance_of(Biscuit)))
183 assert_that(theBiscuit, is_(Biscuit))
173184
174185 *Note that PyHamcrest's ``is_`` matcher is unrelated to Python's ``is``
175186 operator. The matcher for object identity is ``same_instance``.*
186197 eliminate code duplication and make your tests more readable!
187198
188199 Let's write our own matcher for testing if a calendar date falls on a Saturday.
189 This is the test we want to write::
190
191 def testDateIsOnASaturday(self):
192 d = datetime.date(2008, 04, 26)
193 assert_that(d, is_(on_a_saturday()))
194
195 And here's the implementation::
196
197 from hamcrest.core.base_matcher import BaseMatcher
198 from hamcrest.core.helpers.hasmethod import hasmethod
199
200 class IsGivenDayOfWeek(BaseMatcher):
201
202 def __init__(self, day):
203 self.day = day # Monday is 0, Sunday is 6
204
205 def _matches(self, item):
206 if not hasmethod(item, 'weekday'):
207 return False
208 return item.weekday() == self.day
209
210 def describe_to(self, description):
211 day_as_string = ['Monday', 'Tuesday', 'Wednesday', 'Thursday',
212 'Friday', 'Saturday', 'Sunday']
213 description.append_text('calendar date falling on ') \
214 .append_text(day_as_string[self.day])
215
216 def on_a_saturday():
217 return IsGivenDayOfWeek(5)
200 This is the test we want to write:
201
202 .. code:: python
203
204 def testDateIsOnASaturday(self):
205 d = datetime.date(2008, 04, 26)
206 assert_that(d, is_(on_a_saturday()))
207
208 And here's the implementation:
209
210 .. code:: python
211
212 from hamcrest.core.base_matcher import BaseMatcher
213 from hamcrest.core.helpers.hasmethod import hasmethod
214
215 class IsGivenDayOfWeek(BaseMatcher):
216
217 def __init__(self, day):
218 self.day = day # Monday is 0, Sunday is 6
219
220 def _matches(self, item):
221 if not hasmethod(item, 'weekday'):
222 return False
223 return item.weekday() == self.day
224
225 def describe_to(self, description):
226 day_as_string = ['Monday', 'Tuesday', 'Wednesday', 'Thursday',
227 'Friday', 'Saturday', 'Sunday']
228 description.append_text('calendar date falling on ') \
229 .append_text(day_as_string[self.day])
230
231 def on_a_saturday():
232 return IsGivenDayOfWeek(5)
218233
219234 For our Matcher implementation we implement the ``_matches`` method - which
220235 calls the ``weekday`` method after confirming that the argument (which may not
221236 be a date) has such a method - and the ``describe_to`` method - which is used
222237 to produce a failure message when a test fails. Here's an example of how the
223 failure message looks::
224
225 assert_that(datetime.date(2008, 04, 06), is_(on_a_saturday()))
238 failure message looks:
239
240 .. code:: python
241
242 assert_that(datetime.date(2008, 04, 06), is_(on_a_saturday()))
226243
227244 fails with the message::
228245
229 AssertionError:
230 Expected: is calendar date falling on Saturday
231 got: <2008-04-06>
246 AssertionError:
247 Expected: is calendar date falling on Saturday
248 got: <2008-04-06>
232249
233250 Let's say this matcher is saved in a module named ``isgivendayofweek``. We
234 could use it in our test by importing the factory function ``on_a_saturday``::
235
236 from hamcrest import *
237 import unittest
238 from isgivendayofweek import on_a_saturday
239
240 class DateTest(unittest.TestCase):
241 def testDateIsOnASaturday(self):
242 d = datetime.date(2008, 04, 26)
243 assert_that(d, is_(on_a_saturday()))
244
245 if __name__ == '__main__':
246 unittest.main()
251 could use it in our test by importing the factory function ``on_a_saturday``:
252
253 .. code:: python
254
255 from hamcrest import *
256 import unittest
257 from isgivendayofweek import on_a_saturday
258
259 class DateTest(unittest.TestCase):
260 def testDateIsOnASaturday(self):
261 d = datetime.date(2008, 04, 26)
262 assert_that(d, is_(on_a_saturday()))
263
264 if __name__ == '__main__':
265 unittest.main()
247266
248267 Even though the ``on_a_saturday`` function creates a new matcher each time it
249268 is called, you should not assume this is the only usage pattern for your
250269 matcher. Therefore you should make sure your matcher is stateless, so a single
251270 instance can be reused between matches.
271
272
273 More resources
274 ==============
275
276 * Documentation_
277 * Package_
278 * Sources_
279 * Hamcrest_
280
281 .. _Documentation: http://readthedocs.org/docs/pyhamcrest/en/V1.7.1/
282 .. _Package: http://pypi.python.org/pypi/PyHamcrest
283 .. _Sources: https://github.com/hamcrest/PyHamcrest
284 .. _Hamcrest: http://hamcrest.org
252285
253286 Keywords: hamcrest matchers pyunit unit test testing unittest unittesting
254287 Platform: All
261294 Classifier: Programming Language :: Python :: 2.5
262295 Classifier: Programming Language :: Python :: 2.6
263296 Classifier: Programming Language :: Python :: 2.7
264 Classifier: Programming Language :: Python :: 3.1
265297 Classifier: Programming Language :: Python :: 3.2
298 Classifier: Programming Language :: Python :: 3.3
266299 Classifier: Topic :: Software Development
267300 Classifier: Topic :: Software Development :: Quality Assurance
268301 Classifier: Topic :: Software Development :: Testing
+0
-270
PyHamcrest.egg-info/PKG-INFO less more
0 Metadata-Version: 1.1
1 Name: PyHamcrest
2 Version: 1.6
3 Summary: Hamcrest framework for matcher objects
4 Home-page: http://code.google.com/p/hamcrest/
5 Author: Jon Reid
6 Author-email: jon.reid@mac.com
7 License: New BSD
8 Download-URL: http://pypi.python.org/packages/source/P/PyHamcrest/PyHamcrest-1.6.tar.gz
9 Description: * [Full documentation](http://packages.python.org/PyHamcrest)
10 * [Latest package](http://pypi.python.org/pypi/PyHamcrest)
11 * [Latest sources](https://github.com/jonreid/PyHamcrest)
12 * [Hamcrest information](http://code.google.com/p/hamcrest)
13
14 See also:
15
16 * [OCHamcrest](https://github.com/jonreid/OCHamcrest) - Objective-C version for
17 Cocoa and iOS.
18 * [Quality Coding](http://jonreid.blogs.com/qualitycoding/) - Tools, tips and
19 techniques for _building quality in_ to your iOS programs.
20
21
22 Introduction
23 ============
24
25 PyHamcrest is a framework for writing matcher objects, allowing you to
26 declaratively define "match" rules. There are a number of situations where
27 matchers are invaluable, such as UI validation, or data filtering, but it is in
28 the area of writing flexible tests that matchers are most commonly used. This
29 tutorial shows you how to use PyHamcrest for unit testing.
30
31 When writing tests it is sometimes difficult to get the balance right between
32 overspecifying the test (and making it brittle to changes), and not specifying
33 enough (making the test less valuable since it continues to pass even when the
34 thing being tested is broken). Having a tool that allows you to pick out
35 precisely the aspect under test and describe the values it should have, to a
36 controlled level of precision, helps greatly in writing tests that are "just
37 right." Such tests fail when the behavior of the aspect under test deviates
38 from the expected behavior, yet continue to pass when minor, unrelated changes
39 to the behaviour are made.
40
41 Installation
42 ============
43
44 Hamcrest can be installed using the usual Python packaging tools. It depends on
45 distribute, but as long as you have a network connection when you install, the
46 installation process will take care of that for you.
47
48 My first PyHamcrest test
49 ========================
50
51 We'll start by writing a very simple PyUnit test, but instead of using PyUnit's
52 ``assertEqual`` method, we'll use PyHamcrest's ``assert_that`` construct and
53 the standard set of matchers::
54
55 from hamcrest import *
56 import unittest
57
58 class BiscuitTest(unittest.TestCase):
59 def testEquals(self):
60 theBiscuit = Biscuit('Ginger')
61 myBiscuit = Biscuit('Ginger')
62 assert_that(theBiscuit, equal_to(myBiscuit))
63
64 if __name__ == '__main__':
65 unittest.main()
66
67 The ``assert_that`` function is a stylized sentence for making a test
68 assertion. In this example, the subject of the assertion is the object
69 ``theBiscuit``, which is the first method parameter. The second method
70 parameter is a matcher for ``Biscuit`` objects, here a matcher that checks one
71 object is equal to another using the Python ``==`` operator. The test passes
72 since the ``Biscuit`` class defines an ``__eq__`` method.
73
74 If you have more than one assertion in your test you can include an identifier
75 for the tested value in the assertion::
76
77 assert_that(theBiscuit.getChocolateChipCount(), equal_to(10), 'chocolate chips')
78 assert_that(theBiscuit.getHazelnutCount(), equal_to(3), 'hazelnuts')
79
80 As a convenience, assert_that can also be used to verify a boolean condition::
81
82 assert_that(theBiscuit.isCooked(), 'cooked')
83
84 This is equivalent to the ``assert_`` method of unittest.TestCase, but because
85 it's a standalone function, it offers greater flexibility in test writing.
86
87
88 Predefined matchers
89 ===================
90
91 PyHamcrest comes with a library of useful matchers:
92
93 * Object
94
95 * ``equal_to`` - match equal object
96 * ``has_length`` - match ``len()``
97 * ``has_property`` - match value of property with given name
98 * ``has_string`` - match ``str()``
99 * ``instance_of`` - match object type
100 * ``none``, ``not_none`` - match ``None``, or not ``None``
101 * ``same_instance`` - match same object
102
103 * Number
104
105 * ``close_to`` - match number close to a given value
106 * ``greater_than``, ``greater_than_or_equal_to``, ``less_than``,
107 ``less_than_or_equal_to`` - match numeric ordering
108
109 * Text
110
111 * ``contains_string`` - match part of a string
112 * ``ends_with`` - match the end of a string
113 * ``equal_to_ignoring_case`` - match the complete string but ignore case
114 * ``equal_to_ignoring_whitespace`` - match the complete string but ignore
115 extra whitespace
116 * ``starts_with`` - match the beginning of a string
117 * ``string_contains_in_order`` - match parts of a string, in relative order
118
119 * Logical
120
121 * ``all_of`` - ``and`` together all matchers
122 * ``any_of`` - ``or`` together all matchers
123 * ``anything`` - match anything, useful in composite matchers when you don't
124 care about a particular value
125 * ``is_not`` - negate the matcher
126
127 * Sequence
128
129 * ``contains`` - exactly match the entire sequence
130 * ``contains_inanyorder`` - match the entire sequence, but in any order
131 * ``has_item`` - match if given item appears in the sequence
132 * ``has_items`` - match if all given items appear in the sequence, in any
133 order
134 * ``is_in`` - match if item appears in the given sequence
135 * ``only_contains`` - match if sequence's items appear in given list
136
137 * Dictionary
138
139 * ``has_entries`` - match dictionary with list of key-value pairs
140 * ``has_entry`` - match dictionary containing a key-value pair
141 * ``has_key`` - match dictionary with a key
142 * ``has_value`` - match dictionary with a value
143
144 * Decorator
145
146 * ``described_as`` - give the matcher a custom failure description
147 * ``is_`` - decorator to improve readability - see `Syntactic sugar` below
148
149 The arguments for many of these matchers accept not just a matching value, but
150 another matcher, so matchers can be composed for greater flexibility. For
151 example, ``only_contains(less_than(5))`` will match any sequence where every
152 item is less than 5.
153
154
155 Syntactic sugar
156 ===============
157
158 PyHamcrest strives to make your tests as readable as possible. For example, the
159 ``is_`` matcher is a wrapper that doesn't add any extra behavior to the
160 underlying matcher. The following assertions are all equivalent::
161
162 assert_that(theBiscuit, equal_to(myBiscuit))
163 assert_that(theBiscuit, is_(equal_to(myBiscuit)))
164 assert_that(theBiscuit, is_(myBiscuit))
165
166 The last form is allowed since ``is_(value)`` wraps most non-matcher arguments
167 with ``equal_to``. But if the argument is a type, it is wrapped with
168 ``instance_of``, so the following are also equivalent::
169
170 assert_that(theBiscuit, instance_of(Biscuit))
171 assert_that(theBiscuit, is_(instance_of(Biscuit)))
172 assert_that(theBiscuit, is_(Biscuit))
173
174 *Note that PyHamcrest's ``is_`` matcher is unrelated to Python's ``is``
175 operator. The matcher for object identity is ``same_instance``.*
176
177
178 Writing custom matchers
179 =======================
180
181 PyHamcrest comes bundled with lots of useful matchers, but you'll probably find
182 that you need to create your own from time to time to fit your testing needs.
183 This commonly occurs when you find a fragment of code that tests the same set
184 of properties over and over again (and in different tests), and you want to
185 bundle the fragment into a single assertion. By writing your own matcher you'll
186 eliminate code duplication and make your tests more readable!
187
188 Let's write our own matcher for testing if a calendar date falls on a Saturday.
189 This is the test we want to write::
190
191 def testDateIsOnASaturday(self):
192 d = datetime.date(2008, 04, 26)
193 assert_that(d, is_(on_a_saturday()))
194
195 And here's the implementation::
196
197 from hamcrest.core.base_matcher import BaseMatcher
198 from hamcrest.core.helpers.hasmethod import hasmethod
199
200 class IsGivenDayOfWeek(BaseMatcher):
201
202 def __init__(self, day):
203 self.day = day # Monday is 0, Sunday is 6
204
205 def _matches(self, item):
206 if not hasmethod(item, 'weekday'):
207 return False
208 return item.weekday() == self.day
209
210 def describe_to(self, description):
211 day_as_string = ['Monday', 'Tuesday', 'Wednesday', 'Thursday',
212 'Friday', 'Saturday', 'Sunday']
213 description.append_text('calendar date falling on ') \
214 .append_text(day_as_string[self.day])
215
216 def on_a_saturday():
217 return IsGivenDayOfWeek(5)
218
219 For our Matcher implementation we implement the ``_matches`` method - which
220 calls the ``weekday`` method after confirming that the argument (which may not
221 be a date) has such a method - and the ``describe_to`` method - which is used
222 to produce a failure message when a test fails. Here's an example of how the
223 failure message looks::
224
225 assert_that(datetime.date(2008, 04, 06), is_(on_a_saturday()))
226
227 fails with the message::
228
229 AssertionError:
230 Expected: is calendar date falling on Saturday
231 got: <2008-04-06>
232
233 Let's say this matcher is saved in a module named ``isgivendayofweek``. We
234 could use it in our test by importing the factory function ``on_a_saturday``::
235
236 from hamcrest import *
237 import unittest
238 from isgivendayofweek import on_a_saturday
239
240 class DateTest(unittest.TestCase):
241 def testDateIsOnASaturday(self):
242 d = datetime.date(2008, 04, 26)
243 assert_that(d, is_(on_a_saturday()))
244
245 if __name__ == '__main__':
246 unittest.main()
247
248 Even though the ``on_a_saturday`` function creates a new matcher each time it
249 is called, you should not assume this is the only usage pattern for your
250 matcher. Therefore you should make sure your matcher is stateless, so a single
251 instance can be reused between matches.
252
253 Keywords: hamcrest matchers pyunit unit test testing unittest unittesting
254 Platform: All
255 Classifier: Development Status :: 5 - Production/Stable
256 Classifier: Environment :: Console
257 Classifier: Intended Audience :: Developers
258 Classifier: License :: OSI Approved :: BSD License
259 Classifier: Natural Language :: English
260 Classifier: Operating System :: OS Independent
261 Classifier: Programming Language :: Python :: 2.5
262 Classifier: Programming Language :: Python :: 2.6
263 Classifier: Programming Language :: Python :: 2.7
264 Classifier: Programming Language :: Python :: 3.1
265 Classifier: Programming Language :: Python :: 3.2
266 Classifier: Topic :: Software Development
267 Classifier: Topic :: Software Development :: Quality Assurance
268 Classifier: Topic :: Software Development :: Testing
269 Provides: hamcrest
+0
-112
PyHamcrest.egg-info/SOURCES.txt less more
0 CHANGES.txt
1 LICENSE.txt
2 MANIFEST.in
3 README.md
4 setup.cfg
5 setup.py
6 PyHamcrest.egg-info/PKG-INFO
7 PyHamcrest.egg-info/SOURCES.txt
8 PyHamcrest.egg-info/dependency_links.txt
9 PyHamcrest.egg-info/requires.txt
10 PyHamcrest.egg-info/top_level.txt
11 examples/CustomDateMatcher.py
12 examples/ExampleWithAssertThat.py
13 hamcrest/__init__.py
14 hamcrest/core/__init__.py
15 hamcrest/core/assert_that.py
16 hamcrest/core/base_description.py
17 hamcrest/core/base_matcher.py
18 hamcrest/core/description.py
19 hamcrest/core/matcher.py
20 hamcrest/core/selfdescribing.py
21 hamcrest/core/selfdescribingvalue.py
22 hamcrest/core/string_description.py
23 hamcrest/core/core/__init__.py
24 hamcrest/core/core/allof.py
25 hamcrest/core/core/anyof.py
26 hamcrest/core/core/described_as.py
27 hamcrest/core/core/is_.py
28 hamcrest/core/core/isanything.py
29 hamcrest/core/core/isequal.py
30 hamcrest/core/core/isinstanceof.py
31 hamcrest/core/core/isnone.py
32 hamcrest/core/core/isnot.py
33 hamcrest/core/core/issame.py
34 hamcrest/core/helpers/__init__.py
35 hamcrest/core/helpers/hasmethod.py
36 hamcrest/core/helpers/wrap_matcher.py
37 hamcrest/library/__init__.py
38 hamcrest/library/collection/__init__.py
39 hamcrest/library/collection/isdict_containing.py
40 hamcrest/library/collection/isdict_containingentries.py
41 hamcrest/library/collection/isdict_containingkey.py
42 hamcrest/library/collection/isdict_containingvalue.py
43 hamcrest/library/collection/isin.py
44 hamcrest/library/collection/issequence_containing.py
45 hamcrest/library/collection/issequence_containinginanyorder.py
46 hamcrest/library/collection/issequence_containinginorder.py
47 hamcrest/library/collection/issequence_onlycontaining.py
48 hamcrest/library/integration/__init__.py
49 hamcrest/library/integration/match_equality.py
50 hamcrest/library/number/__init__.py
51 hamcrest/library/number/iscloseto.py
52 hamcrest/library/number/ordering_comparison.py
53 hamcrest/library/object/__init__.py
54 hamcrest/library/object/haslength.py
55 hamcrest/library/object/hasproperty.py
56 hamcrest/library/object/hasstring.py
57 hamcrest/library/text/__init__.py
58 hamcrest/library/text/isequal_ignoring_case.py
59 hamcrest/library/text/isequal_ignoring_whitespace.py
60 hamcrest/library/text/stringcontains.py
61 hamcrest/library/text/stringcontainsinorder.py
62 hamcrest/library/text/stringendswith.py
63 hamcrest/library/text/stringstartswith.py
64 hamcrest/library/text/substringmatcher.py
65 hamcrest_unit_test/__init__.py
66 hamcrest_unit_test/alltests.py
67 hamcrest_unit_test/assert_that_test.py
68 hamcrest_unit_test/base_matcher_test.py
69 hamcrest_unit_test/matcher_test.py
70 hamcrest_unit_test/object_import.py
71 hamcrest_unit_test/string_description_test.py
72 hamcrest_unit_test/collection/__init__.py
73 hamcrest_unit_test/collection/isdict_containing_test.py
74 hamcrest_unit_test/collection/isdict_containingentries_test.py
75 hamcrest_unit_test/collection/isdict_containingkey_test.py
76 hamcrest_unit_test/collection/isdict_containingvalue_test.py
77 hamcrest_unit_test/collection/isin_test.py
78 hamcrest_unit_test/collection/issequence_containing_test.py
79 hamcrest_unit_test/collection/issequence_containinginanyorder_test.py
80 hamcrest_unit_test/collection/issequence_containinginorder_test.py
81 hamcrest_unit_test/collection/issequence_onlycontaining_test.py
82 hamcrest_unit_test/collection/quasidict.py
83 hamcrest_unit_test/collection/quasisequence.py
84 hamcrest_unit_test/core/__init__.py
85 hamcrest_unit_test/core/allof_test.py
86 hamcrest_unit_test/core/anyof_test.py
87 hamcrest_unit_test/core/described_as_test.py
88 hamcrest_unit_test/core/is_test.py
89 hamcrest_unit_test/core/isanything_test.py
90 hamcrest_unit_test/core/isequal_test.py
91 hamcrest_unit_test/core/isinstanceof_test.py
92 hamcrest_unit_test/core/isnone_test.py
93 hamcrest_unit_test/core/isnot_test.py
94 hamcrest_unit_test/core/issame_test.py
95 hamcrest_unit_test/core/nevermatch.py
96 hamcrest_unit_test/integration/__init__.py
97 hamcrest_unit_test/integration/match_equality_test.py
98 hamcrest_unit_test/number/__init__.py
99 hamcrest_unit_test/number/iscloseto_test.py
100 hamcrest_unit_test/number/ordering_comparison_test.py
101 hamcrest_unit_test/object/__init__.py
102 hamcrest_unit_test/object/haslength_test.py
103 hamcrest_unit_test/object/hasproperty_test.py
104 hamcrest_unit_test/object/hasstring_test.py
105 hamcrest_unit_test/text/__init__.py
106 hamcrest_unit_test/text/isequal_ignoring_case_test.py
107 hamcrest_unit_test/text/isequal_ignoring_whitespace_test.py
108 hamcrest_unit_test/text/stringcontains_test.py
109 hamcrest_unit_test/text/stringcontainsinorder_test.py
110 hamcrest_unit_test/text/stringendswith_test.py
111 hamcrest_unit_test/text/stringstartswith_test.py
+0
-1
PyHamcrest.egg-info/dependency_links.txt less more
0
+0
-1
PyHamcrest.egg-info/requires.txt less more
0 distribute
+0
-2
PyHamcrest.egg-info/top_level.txt less more
0 hamcrest_unit_test
1 hamcrest
+0
-243
README.md less more
0 * [Full documentation](http://packages.python.org/PyHamcrest)
1 * [Latest package](http://pypi.python.org/pypi/PyHamcrest)
2 * [Latest sources](https://github.com/jonreid/PyHamcrest)
3 * [Hamcrest information](http://code.google.com/p/hamcrest)
4
5 See also:
6
7 * [OCHamcrest](https://github.com/jonreid/OCHamcrest) - Objective-C version for
8 Cocoa and iOS.
9 * [Quality Coding](http://jonreid.blogs.com/qualitycoding/) - Tools, tips and
10 techniques for _building quality in_ to your iOS programs.
11
12
13 Introduction
14 ============
15
16 PyHamcrest is a framework for writing matcher objects, allowing you to
17 declaratively define "match" rules. There are a number of situations where
18 matchers are invaluable, such as UI validation, or data filtering, but it is in
19 the area of writing flexible tests that matchers are most commonly used. This
20 tutorial shows you how to use PyHamcrest for unit testing.
21
22 When writing tests it is sometimes difficult to get the balance right between
23 overspecifying the test (and making it brittle to changes), and not specifying
24 enough (making the test less valuable since it continues to pass even when the
25 thing being tested is broken). Having a tool that allows you to pick out
26 precisely the aspect under test and describe the values it should have, to a
27 controlled level of precision, helps greatly in writing tests that are "just
28 right." Such tests fail when the behavior of the aspect under test deviates
29 from the expected behavior, yet continue to pass when minor, unrelated changes
30 to the behaviour are made.
31
32 Installation
33 ============
34
35 Hamcrest can be installed using the usual Python packaging tools. It depends on
36 distribute, but as long as you have a network connection when you install, the
37 installation process will take care of that for you.
38
39 My first PyHamcrest test
40 ========================
41
42 We'll start by writing a very simple PyUnit test, but instead of using PyUnit's
43 ``assertEqual`` method, we'll use PyHamcrest's ``assert_that`` construct and
44 the standard set of matchers::
45
46 from hamcrest import *
47 import unittest
48
49 class BiscuitTest(unittest.TestCase):
50 def testEquals(self):
51 theBiscuit = Biscuit('Ginger')
52 myBiscuit = Biscuit('Ginger')
53 assert_that(theBiscuit, equal_to(myBiscuit))
54
55 if __name__ == '__main__':
56 unittest.main()
57
58 The ``assert_that`` function is a stylized sentence for making a test
59 assertion. In this example, the subject of the assertion is the object
60 ``theBiscuit``, which is the first method parameter. The second method
61 parameter is a matcher for ``Biscuit`` objects, here a matcher that checks one
62 object is equal to another using the Python ``==`` operator. The test passes
63 since the ``Biscuit`` class defines an ``__eq__`` method.
64
65 If you have more than one assertion in your test you can include an identifier
66 for the tested value in the assertion::
67
68 assert_that(theBiscuit.getChocolateChipCount(), equal_to(10), 'chocolate chips')
69 assert_that(theBiscuit.getHazelnutCount(), equal_to(3), 'hazelnuts')
70
71 As a convenience, assert_that can also be used to verify a boolean condition::
72
73 assert_that(theBiscuit.isCooked(), 'cooked')
74
75 This is equivalent to the ``assert_`` method of unittest.TestCase, but because
76 it's a standalone function, it offers greater flexibility in test writing.
77
78
79 Predefined matchers
80 ===================
81
82 PyHamcrest comes with a library of useful matchers:
83
84 * Object
85
86 * ``equal_to`` - match equal object
87 * ``has_length`` - match ``len()``
88 * ``has_property`` - match value of property with given name
89 * ``has_string`` - match ``str()``
90 * ``instance_of`` - match object type
91 * ``none``, ``not_none`` - match ``None``, or not ``None``
92 * ``same_instance`` - match same object
93
94 * Number
95
96 * ``close_to`` - match number close to a given value
97 * ``greater_than``, ``greater_than_or_equal_to``, ``less_than``,
98 ``less_than_or_equal_to`` - match numeric ordering
99
100 * Text
101
102 * ``contains_string`` - match part of a string
103 * ``ends_with`` - match the end of a string
104 * ``equal_to_ignoring_case`` - match the complete string but ignore case
105 * ``equal_to_ignoring_whitespace`` - match the complete string but ignore
106 extra whitespace
107 * ``starts_with`` - match the beginning of a string
108 * ``string_contains_in_order`` - match parts of a string, in relative order
109
110 * Logical
111
112 * ``all_of`` - ``and`` together all matchers
113 * ``any_of`` - ``or`` together all matchers
114 * ``anything`` - match anything, useful in composite matchers when you don't
115 care about a particular value
116 * ``is_not`` - negate the matcher
117
118 * Sequence
119
120 * ``contains`` - exactly match the entire sequence
121 * ``contains_inanyorder`` - match the entire sequence, but in any order
122 * ``has_item`` - match if given item appears in the sequence
123 * ``has_items`` - match if all given items appear in the sequence, in any
124 order
125 * ``is_in`` - match if item appears in the given sequence
126 * ``only_contains`` - match if sequence's items appear in given list
127
128 * Dictionary
129
130 * ``has_entries`` - match dictionary with list of key-value pairs
131 * ``has_entry`` - match dictionary containing a key-value pair
132 * ``has_key`` - match dictionary with a key
133 * ``has_value`` - match dictionary with a value
134
135 * Decorator
136
137 * ``described_as`` - give the matcher a custom failure description
138 * ``is_`` - decorator to improve readability - see `Syntactic sugar` below
139
140 The arguments for many of these matchers accept not just a matching value, but
141 another matcher, so matchers can be composed for greater flexibility. For
142 example, ``only_contains(less_than(5))`` will match any sequence where every
143 item is less than 5.
144
145
146 Syntactic sugar
147 ===============
148
149 PyHamcrest strives to make your tests as readable as possible. For example, the
150 ``is_`` matcher is a wrapper that doesn't add any extra behavior to the
151 underlying matcher. The following assertions are all equivalent::
152
153 assert_that(theBiscuit, equal_to(myBiscuit))
154 assert_that(theBiscuit, is_(equal_to(myBiscuit)))
155 assert_that(theBiscuit, is_(myBiscuit))
156
157 The last form is allowed since ``is_(value)`` wraps most non-matcher arguments
158 with ``equal_to``. But if the argument is a type, it is wrapped with
159 ``instance_of``, so the following are also equivalent::
160
161 assert_that(theBiscuit, instance_of(Biscuit))
162 assert_that(theBiscuit, is_(instance_of(Biscuit)))
163 assert_that(theBiscuit, is_(Biscuit))
164
165 *Note that PyHamcrest's ``is_`` matcher is unrelated to Python's ``is``
166 operator. The matcher for object identity is ``same_instance``.*
167
168
169 Writing custom matchers
170 =======================
171
172 PyHamcrest comes bundled with lots of useful matchers, but you'll probably find
173 that you need to create your own from time to time to fit your testing needs.
174 This commonly occurs when you find a fragment of code that tests the same set
175 of properties over and over again (and in different tests), and you want to
176 bundle the fragment into a single assertion. By writing your own matcher you'll
177 eliminate code duplication and make your tests more readable!
178
179 Let's write our own matcher for testing if a calendar date falls on a Saturday.
180 This is the test we want to write::
181
182 def testDateIsOnASaturday(self):
183 d = datetime.date(2008, 04, 26)
184 assert_that(d, is_(on_a_saturday()))
185
186 And here's the implementation::
187
188 from hamcrest.core.base_matcher import BaseMatcher
189 from hamcrest.core.helpers.hasmethod import hasmethod
190
191 class IsGivenDayOfWeek(BaseMatcher):
192
193 def __init__(self, day):
194 self.day = day # Monday is 0, Sunday is 6
195
196 def _matches(self, item):
197 if not hasmethod(item, 'weekday'):
198 return False
199 return item.weekday() == self.day
200
201 def describe_to(self, description):
202 day_as_string = ['Monday', 'Tuesday', 'Wednesday', 'Thursday',
203 'Friday', 'Saturday', 'Sunday']
204 description.append_text('calendar date falling on ') \
205 .append_text(day_as_string[self.day])
206
207 def on_a_saturday():
208 return IsGivenDayOfWeek(5)
209
210 For our Matcher implementation we implement the ``_matches`` method - which
211 calls the ``weekday`` method after confirming that the argument (which may not
212 be a date) has such a method - and the ``describe_to`` method - which is used
213 to produce a failure message when a test fails. Here's an example of how the
214 failure message looks::
215
216 assert_that(datetime.date(2008, 04, 06), is_(on_a_saturday()))
217
218 fails with the message::
219
220 AssertionError:
221 Expected: is calendar date falling on Saturday
222 got: <2008-04-06>
223
224 Let's say this matcher is saved in a module named ``isgivendayofweek``. We
225 could use it in our test by importing the factory function ``on_a_saturday``::
226
227 from hamcrest import *
228 import unittest
229 from isgivendayofweek import on_a_saturday
230
231 class DateTest(unittest.TestCase):
232 def testDateIsOnASaturday(self):
233 d = datetime.date(2008, 04, 26)
234 assert_that(d, is_(on_a_saturday()))
235
236 if __name__ == '__main__':
237 unittest.main()
238
239 Even though the ``on_a_saturday`` function creates a new matcher each time it
240 is called, you should not assume this is the only usage pattern for your
241 matcher. Therefore you should make sure your matcher is stateless, so a single
242 instance can be reused between matches.
0 PyHamcrest
1 ==========
2
3 .. image:: https://pypip.in/v/PyHamcrest/badge.png
4 :alt: Release Status
5 :target: https://crate.io/packages/PyHamcrest
6 .. image:: https://pypip.in/d/PyHamcrest/badge.png
7 :alt: Downloads
8 :target: https://crate.io/packages/PyHamcrest
9 .. image:: https://travis-ci.org/hamcrest/PyHamcrest.png?branch=master
10 :alt: Build Status
11 :target: https://travis-ci.org/hamcrest/PyHamcrest
12
13 Introduction
14 ============
15
16 PyHamcrest is a framework for writing matcher objects, allowing you to
17 declaratively define "match" rules. There are a number of situations where
18 matchers are invaluable, such as UI validation, or data filtering, but it is in
19 the area of writing flexible tests that matchers are most commonly used. This
20 tutorial shows you how to use PyHamcrest for unit testing.
21
22 When writing tests it is sometimes difficult to get the balance right between
23 overspecifying the test (and making it brittle to changes), and not specifying
24 enough (making the test less valuable since it continues to pass even when the
25 thing being tested is broken). Having a tool that allows you to pick out
26 precisely the aspect under test and describe the values it should have, to a
27 controlled level of precision, helps greatly in writing tests that are "just
28 right." Such tests fail when the behavior of the aspect under test deviates
29 from the expected behavior, yet continue to pass when minor, unrelated changes
30 to the behaviour are made.
31
32 Installation
33 ============
34
35 Hamcrest can be installed using the usual Python packaging tools. It depends on
36 distribute, but as long as you have a network connection when you install, the
37 installation process will take care of that for you.
38
39 My first PyHamcrest test
40 ========================
41
42 We'll start by writing a very simple PyUnit test, but instead of using PyUnit's
43 ``assertEqual`` method, we'll use PyHamcrest's ``assert_that`` construct and
44 the standard set of matchers:
45
46 .. code:: python
47
48 from hamcrest import *
49 import unittest
50
51 class BiscuitTest(unittest.TestCase):
52 def testEquals(self):
53 theBiscuit = Biscuit('Ginger')
54 myBiscuit = Biscuit('Ginger')
55 assert_that(theBiscuit, equal_to(myBiscuit))
56
57 if __name__ == '__main__':
58 unittest.main()
59
60 The ``assert_that`` function is a stylized sentence for making a test
61 assertion. In this example, the subject of the assertion is the object
62 ``theBiscuit``, which is the first method parameter. The second method
63 parameter is a matcher for ``Biscuit`` objects, here a matcher that checks one
64 object is equal to another using the Python ``==`` operator. The test passes
65 since the ``Biscuit`` class defines an ``__eq__`` method.
66
67 If you have more than one assertion in your test you can include an identifier
68 for the tested value in the assertion:
69
70 .. code:: python
71
72 assert_that(theBiscuit.getChocolateChipCount(), equal_to(10), 'chocolate chips')
73 assert_that(theBiscuit.getHazelnutCount(), equal_to(3), 'hazelnuts')
74
75 As a convenience, assert_that can also be used to verify a boolean condition:
76
77 .. code:: python
78
79 assert_that(theBiscuit.isCooked(), 'cooked')
80
81 This is equivalent to the ``assert_`` method of unittest.TestCase, but because
82 it's a standalone function, it offers greater flexibility in test writing.
83
84
85 Predefined matchers
86 ===================
87
88 PyHamcrest comes with a library of useful matchers:
89
90 * Object
91
92 * ``equal_to`` - match equal object
93 * ``has_length`` - match ``len()``
94 * ``has_property`` - match value of property with given name
95 * ``has_properties`` - match an object that has all of the given properties.
96 * ``has_string`` - match ``str()``
97 * ``instance_of`` - match object type
98 * ``none``, ``not_none`` - match ``None``, or not ``None``
99 * ``same_instance`` - match same object
100
101 * Number
102
103 * ``close_to`` - match number close to a given value
104 * ``greater_than``, ``greater_than_or_equal_to``, ``less_than``,
105 ``less_than_or_equal_to`` - match numeric ordering
106
107 * Text
108
109 * ``contains_string`` - match part of a string
110 * ``ends_with`` - match the end of a string
111 * ``equal_to_ignoring_case`` - match the complete string but ignore case
112 * ``equal_to_ignoring_whitespace`` - match the complete string but ignore extra whitespace
113 * ``matches_regexp`` - match a regular expression in a string
114 * ``starts_with`` - match the beginning of a string
115 * ``string_contains_in_order`` - match parts of a string, in relative order
116
117 * Logical
118
119 * ``all_of`` - ``and`` together all matchers
120 * ``any_of`` - ``or`` together all matchers
121 * ``anything`` - match anything, useful in composite matchers when you don't care about a particular value
122 * ``is_not`` - negate the matcher
123
124 * Sequence
125
126 * ``contains`` - exactly match the entire sequence
127 * ``contains_inanyorder`` - match the entire sequence, but in any order
128 * ``has_item`` - match if given item appears in the sequence
129 * ``has_items`` - match if all given items appear in the sequence, in any order
130 * ``is_in`` - match if item appears in the given sequence
131 * ``only_contains`` - match if sequence's items appear in given list
132
133 * Dictionary
134
135 * ``has_entries`` - match dictionary with list of key-value pairs
136 * ``has_entry`` - match dictionary containing a key-value pair
137 * ``has_key`` - match dictionary with a key
138 * ``has_value`` - match dictionary with a value
139
140 * Decorator
141
142 * ``calling`` - wrap a callable in a deffered object, for subsequent matching on calling behaviour
143 * ``raises`` - Ensure that a deferred callable raises as expected
144 * ``described_as`` - give the matcher a custom failure description
145 * ``is_`` - decorator to improve readability - see `Syntactic sugar` below
146
147 The arguments for many of these matchers accept not just a matching value, but
148 another matcher, so matchers can be composed for greater flexibility. For
149 example, ``only_contains(less_than(5))`` will match any sequence where every
150 item is less than 5.
151
152
153 Syntactic sugar
154 ===============
155
156 PyHamcrest strives to make your tests as readable as possible. For example, the
157 ``is_`` matcher is a wrapper that doesn't add any extra behavior to the
158 underlying matcher. The following assertions are all equivalent:
159
160 .. code:: python
161
162 assert_that(theBiscuit, equal_to(myBiscuit))
163 assert_that(theBiscuit, is_(equal_to(myBiscuit)))
164 assert_that(theBiscuit, is_(myBiscuit))
165
166 The last form is allowed since ``is_(value)`` wraps most non-matcher arguments
167 with ``equal_to``. But if the argument is a type, it is wrapped with
168 ``instance_of``, so the following are also equivalent:
169
170 .. code:: python
171
172 assert_that(theBiscuit, instance_of(Biscuit))
173 assert_that(theBiscuit, is_(instance_of(Biscuit)))
174 assert_that(theBiscuit, is_(Biscuit))
175
176 *Note that PyHamcrest's ``is_`` matcher is unrelated to Python's ``is``
177 operator. The matcher for object identity is ``same_instance``.*
178
179
180 Writing custom matchers
181 =======================
182
183 PyHamcrest comes bundled with lots of useful matchers, but you'll probably find
184 that you need to create your own from time to time to fit your testing needs.
185 This commonly occurs when you find a fragment of code that tests the same set
186 of properties over and over again (and in different tests), and you want to
187 bundle the fragment into a single assertion. By writing your own matcher you'll
188 eliminate code duplication and make your tests more readable!
189
190 Let's write our own matcher for testing if a calendar date falls on a Saturday.
191 This is the test we want to write:
192
193 .. code:: python
194
195 def testDateIsOnASaturday(self):
196 d = datetime.date(2008, 04, 26)
197 assert_that(d, is_(on_a_saturday()))
198
199 And here's the implementation:
200
201 .. code:: python
202
203 from hamcrest.core.base_matcher import BaseMatcher
204 from hamcrest.core.helpers.hasmethod import hasmethod
205
206 class IsGivenDayOfWeek(BaseMatcher):
207
208 def __init__(self, day):
209 self.day = day # Monday is 0, Sunday is 6
210
211 def _matches(self, item):
212 if not hasmethod(item, 'weekday'):
213 return False
214 return item.weekday() == self.day
215
216 def describe_to(self, description):
217 day_as_string = ['Monday', 'Tuesday', 'Wednesday', 'Thursday',
218 'Friday', 'Saturday', 'Sunday']
219 description.append_text('calendar date falling on ') \
220 .append_text(day_as_string[self.day])
221
222 def on_a_saturday():
223 return IsGivenDayOfWeek(5)
224
225 For our Matcher implementation we implement the ``_matches`` method - which
226 calls the ``weekday`` method after confirming that the argument (which may not
227 be a date) has such a method - and the ``describe_to`` method - which is used
228 to produce a failure message when a test fails. Here's an example of how the
229 failure message looks:
230
231 .. code:: python
232
233 assert_that(datetime.date(2008, 04, 06), is_(on_a_saturday()))
234
235 fails with the message::
236
237 AssertionError:
238 Expected: is calendar date falling on Saturday
239 got: <2008-04-06>
240
241 Let's say this matcher is saved in a module named ``isgivendayofweek``. We
242 could use it in our test by importing the factory function ``on_a_saturday``:
243
244 .. code:: python
245
246 from hamcrest import *
247 import unittest
248 from isgivendayofweek import on_a_saturday
249
250 class DateTest(unittest.TestCase):
251 def testDateIsOnASaturday(self):
252 d = datetime.date(2008, 04, 26)
253 assert_that(d, is_(on_a_saturday()))
254
255 if __name__ == '__main__':
256 unittest.main()
257
258 Even though the ``on_a_saturday`` function creates a new matcher each time it
259 is called, you should not assume this is the only usage pattern for your
260 matcher. Therefore you should make sure your matcher is stateless, so a single
261 instance can be reused between matches.
262
263
264 More resources
265 ==============
266
267 * Documentation_
268 * Package_
269 * Sources_
270 * Hamcrest_
271
272 .. _Documentation: http://readthedocs.org/docs/pyhamcrest/en/V1.7.1/
273 .. _Package: http://pypi.python.org/pypi/PyHamcrest
274 .. _Sources: https://github.com/hamcrest/PyHamcrest
275 .. _Hamcrest: http://hamcrest.org
+0
-7
hamcrest/__init__.py less more
0 from core import *
1 from library import *
2
3 __version__ = "1.6"
4 __author__ = "Jon Reid"
5 __copyright__ = "Copyright 2011 hamcrest.org"
6 __license__ = "BSD, see License.txt"
hamcrest/core/._base_matcher.py less more
Binary diff not shown
+0
-6
hamcrest/core/__init__.py less more
0 from assert_that import assert_that
1 from core import *
2
3 __author__ = "Jon Reid"
4 __copyright__ = "Copyright 2011 hamcrest.org"
5 __license__ = "BSD, see License.txt"
+0
-61
hamcrest/core/assert_that.py less more
0 from matcher import Matcher
1 from string_description import StringDescription
2
3 __author__ = "Jon Reid"
4 __copyright__ = "Copyright 2011 hamcrest.org"
5 __license__ = "BSD, see License.txt"
6 __unittest = True
7
8
9 def assert_that(arg1, arg2=None, arg3=''):
10 """Asserts that actual value satisfies matcher. (Can also assert plain
11 boolean condition.)
12
13 :param actual: The object to evaluate as the actual value.
14 :param matcher: The matcher to satisfy as the expected condition.
15 :param reason: Optional explanation to include in failure description.
16
17 ``assert_that`` passes the actual value to the matcher for evaluation. If
18 the matcher is not satisfied, an exception is thrown describing the
19 mismatch.
20
21 ``assert_that`` is designed to integrate well with PyUnit and other unit
22 testing frameworks. The exception raised for an unmet assertion is an
23 :py:exc:`AssertionError`, which PyUnit reports as a test failure.
24
25 With a different set of parameters, ``assert_that`` can also verify a
26 boolean condition:
27
28 .. function:: assert_that(assertion[, reason])
29
30 :param assertion: Boolean condition to verify.
31 :param reason: Optional explanation to include in failure description.
32
33 This is equivalent to the :py:meth:`~unittest.TestCase.assertTrue` method
34 of :py:class:`unittest.TestCase`, but offers greater flexibility in test
35 writing by being a standalone function.
36
37 """
38 if isinstance(arg2, Matcher):
39 _assert_match(actual=arg1, matcher=arg2, reason=arg3)
40 else:
41 _assert_bool(assertion=arg1, reason=arg2)
42
43
44 def _assert_match(actual, matcher, reason):
45 if not matcher.matches(actual):
46 description = StringDescription()
47 description.append_text(reason) \
48 .append_text('\nExpected: ') \
49 .append_description_of(matcher) \
50 .append_text('\n but: ')
51 matcher.describe_mismatch(actual, description)
52 description.append_text('\n')
53 raise AssertionError(str(description))
54
55
56 def _assert_bool(assertion, reason=None):
57 if not assertion:
58 if not reason:
59 reason = 'Assertion failed'
60 raise AssertionError(reason)
+0
-89
hamcrest/core/base_description.py less more
0 from description import Description
1 from selfdescribingvalue import SelfDescribingValue
2 from helpers.hasmethod import hasmethod
3
4 import warnings
5
6 __author__ = "Jon Reid"
7 __copyright__ = "Copyright 2011 hamcrest.org"
8 __license__ = "BSD, see License.txt"
9
10
11 class BaseDescription(Description):
12 """Base class for all :py:class:`~hamcrest.core.description.Description`
13 implementations.
14
15 """
16
17 def append_text(self, text):
18 self.append(text)
19 return self
20
21 def append_description_of(self, value):
22 if hasmethod(value, 'describe_to'):
23 value.describe_to(self)
24 elif isinstance(value, str):
25 self.append_string_in_python_syntax(value)
26 elif isinstance(value, unicode):
27 self.append(repr(value))
28 else:
29 description = str(value)
30 if description[:1] == '<' and description[-1:] == '>':
31 self.append(description)
32 else:
33 self.append('<')
34 self.append(description)
35 self.append('>')
36 return self
37
38 def append_value(self, value):
39 warnings.warn('Call append_description_of instead of append_value',
40 DeprecationWarning)
41 if isinstance(value, str):
42 self.append_string_in_python_syntax(value)
43 else:
44 self.append('<')
45 self.append(str(value))
46 self.append('>')
47 return self
48
49 def append_value_list(self, start, separator, end, list):
50 warnings.warn('Call append_list instead of append_value_list',
51 DeprecationWarning)
52 return self.append_list(start, separator, end,
53 map(SelfDescribingValue, list))
54
55 def append_list(self, start, separator, end, list):
56 separate = False
57
58 self.append(start)
59 for item in list:
60 if separate:
61 self.append(separator)
62 self.append_description_of(item)
63 separate = True
64 self.append(end)
65 return self
66
67 def append(self, string):
68 """Append the string to the description."""
69 raise NotImplementedError('append')
70
71 def append_string_in_python_syntax(self, string):
72 self.append("'")
73 for ch in string:
74 self.append(character_in_python_syntax(ch))
75 self.append("'")
76
77
78 def character_in_python_syntax(ch):
79 if ch == "'":
80 return "\'"
81 elif ch == '\n':
82 return '\\n'
83 elif ch == '\r':
84 return '\\r'
85 elif ch == '\t':
86 return '\\t'
87 else:
88 return ch
+0
-33
hamcrest/core/base_matcher.py less more
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4 from matcher import Matcher
5 from string_description import tostring
6
7
8 class BaseMatcher(Matcher):
9 """Base class for all :py:class:`~hamcrest.core.matcher.Matcher`
10 implementations.
11
12 Most implementations can just implement :py:obj:`_matches`, leaving the
13 handling of any mismatch description to the ``matches`` method. But if it
14 makes more sense to generate the mismatch description during the matching,
15 override :py:meth:`~hamcrest.core.matcher.Matcher.matches` instead.
16
17 """
18
19 def __str__(self):
20 return tostring(self)
21
22 def _matches(self, item):
23 raise NotImplementedError('_matches')
24
25 def matches(self, item, mismatch_description=None):
26 match_result = self._matches(item)
27 if not match_result and mismatch_description:
28 self.describe_mismatch(item, mismatch_description)
29 return match_result
30
31 def describe_mismatch(self, item, mismatch_description):
32 mismatch_description.append_text('was ').append_description_of(item)
+0
-16
hamcrest/core/core/__init__.py less more
0 """Fundamental matchers of objects and values, and composite matchers."""
1
2 from allof import all_of
3 from anyof import any_of
4 from described_as import described_as
5 from is_ import is_
6 from isanything import anything
7 from isequal import equal_to
8 from isinstanceof import instance_of
9 from isnone import none, not_none
10 from isnot import is_not
11 from issame import same_instance
12
13 __author__ = "Jon Reid"
14 __copyright__ = "Copyright 2011 hamcrest.org"
15 __license__ = "BSD, see License.txt"
+0
-44
hamcrest/core/core/allof.py less more
0 from hamcrest.core.base_matcher import BaseMatcher
1 from hamcrest.core.helpers.wrap_matcher import wrap_matcher
2
3 __author__ = "Jon Reid"
4 __copyright__ = "Copyright 2011 hamcrest.org"
5 __license__ = "BSD, see License.txt"
6
7
8 class AllOf(BaseMatcher):
9
10 def __init__(self, *matchers):
11 self.matchers = matchers
12
13 def matches(self, item, mismatch_description=None):
14 for matcher in self.matchers:
15 if not matcher.matches(item):
16 if mismatch_description:
17 mismatch_description.append_description_of(matcher) \
18 .append_text(' ')
19 matcher.describe_mismatch(item, mismatch_description)
20 return False
21 return True
22
23 def describe_mismatch(self, item, mismatch_description):
24 self.matches(item, mismatch_description)
25
26 def describe_to(self, description):
27 description.append_list('(', ' and ', ')', self.matchers)
28
29
30 def all_of(*items):
31 """Matches if all of the given matchers evaluate to ``True``.
32
33 :param matcher1,...: A comma-separated list of matchers.
34
35 The matchers are evaluated from left to right using short-circuit
36 evaluation, so evaluation stops as soon as a matcher returns ``False``.
37
38 Any argument that is not a matcher is implicitly wrapped in an
39 :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
40 equality.
41
42 """
43 return AllOf(*[wrap_matcher(item) for item in items])
+0
-37
hamcrest/core/core/anyof.py less more
0 from hamcrest.core.base_matcher import BaseMatcher
1 from hamcrest.core.helpers.wrap_matcher import wrap_matcher
2
3 __author__ = "Jon Reid"
4 __copyright__ = "Copyright 2011 hamcrest.org"
5 __license__ = "BSD, see License.txt"
6
7
8 class AnyOf(BaseMatcher):
9
10 def __init__(self, *matchers):
11 self.matchers = matchers
12
13 def _matches(self, item):
14 for matcher in self.matchers:
15 if matcher.matches(item):
16 return True
17 return False
18
19 def describe_to(self, description):
20 description.append_list('(', ' or ', ')', self.matchers)
21
22
23 def any_of(*items):
24 """Matches if any of the given matchers evaluate to ``True``.
25
26 :param matcher1,...: A comma-separated list of matchers.
27
28 The matchers are evaluated from left to right using short-circuit
29 evaluation, so evaluation stops as soon as a matcher returns ``True``.
30
31 Any argument that is not a matcher is implicitly wrapped in an
32 :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
33 equality.
34
35 """
36 return AnyOf(*[wrap_matcher(item) for item in items])
+0
-49
hamcrest/core/core/described_as.py less more
0 import re
1
2 from hamcrest.core.base_matcher import BaseMatcher
3
4 __author__ = "Jon Reid"
5 __copyright__ = "Copyright 2011 hamcrest.org"
6 __license__ = "BSD, see License.txt"
7
8
9 ARG_PATTERN = re.compile('%([0-9]+)')
10
11
12 class DescribedAs(BaseMatcher):
13
14 def __init__(self, description_template, matcher, *values):
15 self.template = description_template
16 self.matcher = matcher
17 self.values = values
18
19 def matches(self, item, mismatch_description=None):
20 return self.matcher.matches(item, mismatch_description)
21
22 def describe_mismatch(self, item, mismatch_description):
23 self.matcher.describe_mismatch(item, mismatch_description)
24
25 def describe_to(self, description):
26 text_start = 0
27 for match in re.finditer(ARG_PATTERN, self.template):
28 description.append_text(self.template[text_start:match.start()])
29 arg_index = int(match.group()[1:])
30 description.append_description_of(self.values[arg_index])
31 text_start = match.end()
32
33 if text_start < len(self.template):
34 description.append_text(self.template[text_start:])
35
36
37 def described_as(description, matcher, *values):
38 """Adds custom failure description to a given matcher.
39
40 :param description: Overrides the matcher's description.
41 :param matcher: The matcher to satisfy.
42 :param value1,...: Optional comma-separated list of substitution values.
43
44 The description may contain substitution placeholders %0, %1, etc. These
45 will be replaced by any values that follow the matcher.
46
47 """
48 return DescribedAs(description, matcher, *values)
+0
-75
hamcrest/core/core/is_.py less more
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4 from hamcrest.core.base_matcher import BaseMatcher
5 from hamcrest.core.helpers.wrap_matcher import wrap_matcher
6 from isinstanceof import instance_of
7
8
9 class Is(BaseMatcher):
10
11 def __init__(self, matcher):
12 self.matcher = matcher
13
14 def matches(self, item, mismatch_description=None):
15 return self.matcher.matches(item, mismatch_description)
16
17 def describe_mismatch(self, item, mismatch_description):
18 return self.matcher.describe_mismatch(item, mismatch_description)
19
20 def describe_to(self, description):
21 description.append_description_of(self.matcher)
22
23
24 def wrap_value_or_type(x):
25 if isinstance(x, type):
26 return instance_of(x)
27 else:
28 return wrap_matcher(x)
29
30
31 def is_(x):
32 """Decorates another matcher, or provides shortcuts to the frequently used
33 ``is(equal_to(x))`` and ``is(instance_of(x))``.
34
35 :param x: The matcher to satisfy, or a type for
36 :py:func:`~hamcrest.core.core.isinstanceof.instance_of` matching, or an
37 expected value for :py:func:`~hamcrest.core.core.isequal.equal_to`
38 matching.
39
40 This matcher compares the evaluated object to the given matcher.
41
42 .. note::
43
44 PyHamcrest's ``is_`` matcher is unrelated to Python's ``is`` operator.
45 The matcher for object identity is
46 :py:func:`~hamcrest.core.core.issame.same_instance`.
47
48 If the ``x`` argument is a matcher, its behavior is retained, but the test
49 may be more expressive. For example::
50
51 assert_that(value, less_than(5))
52 assert_that(value, is_(less_than(5)))
53
54 If the ``x`` argument is a type, it is wrapped in an
55 :py:func:`~hamcrest.core.core.isinstanceof.instance_of` matcher. This makes
56 the following statements equivalent::
57
58 assert_that(cheese, instance_of(Cheddar))
59 assert_that(cheese, is_(instance_of(Cheddar)))
60 assert_that(cheese, is_(Cheddar))
61
62 Otherwise, if the ``x`` argument is not a matcher, it is wrapped in an
63 :py:func:`~hamcrest.core.core.isequal.equal_to` matcher. This makes the
64 following statements equivalent::
65
66 assert_that(cheese, equal_to(smelly))
67 assert_that(cheese, is_(equal_to(smelly)))
68 assert_that(cheese, is_(smelly))
69
70 Choose the style that makes your expression most readable. This will vary
71 depending on context.
72
73 """
74 return Is(wrap_value_or_type(x))
+0
-31
hamcrest/core/core/isanything.py less more
0 from hamcrest.core.base_matcher import BaseMatcher
1
2 __author__ = "Jon Reid"
3 __copyright__ = "Copyright 2011 hamcrest.org"
4 __license__ = "BSD, see License.txt"
5
6
7 class IsAnything(BaseMatcher):
8
9 def __init__(self, description):
10 self.description = description
11 if not description:
12 self.description = 'ANYTHING'
13
14 def _matches(self, item):
15 return True
16
17 def describe_to(self, description):
18 description.append_text(self.description)
19
20
21 def anything(description=None):
22 """Matches anything.
23
24 :param description: Optional string used to describe this matcher.
25
26 This matcher always evaluates to ``True``. Specify this in composite
27 matchers when the value of a particular element is unimportant.
28
29 """
30 return IsAnything(description)
+0
-32
hamcrest/core/core/isequal.py less more
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4 from hamcrest.core.base_matcher import BaseMatcher
5 from hamcrest.core.matcher import Matcher
6
7
8 class IsEqual(BaseMatcher):
9
10 def __init__(self, equals):
11 self.object = equals
12
13 def _matches(self, item):
14 return item == self.object
15
16 def describe_to(self, description):
17 nested_matcher = isinstance(self.object, Matcher)
18 if nested_matcher:
19 description.append_text('<')
20 description.append_description_of(self.object)
21 if nested_matcher:
22 description.append_text('>')
23
24
25 def equal_to(obj):
26 """Matches if object is equal to a given object.
27
28 :param obj: The object to compare against as the expected value.
29
30 This matcher compares the evaluated object to ``obj`` for equality."""
31 return IsEqual(obj)
+0
-36
hamcrest/core/core/isinstanceof.py less more
0 from hamcrest.core.base_matcher import BaseMatcher
1
2 __author__ = "Jon Reid"
3 __copyright__ = "Copyright 2011 hamcrest.org"
4 __license__ = "BSD, see License.txt"
5
6
7 class IsInstanceOf(BaseMatcher):
8
9 def __init__(self, expected_type):
10 if not isinstance(expected_type, type):
11 raise TypeError('IsInstanceOf requires type')
12 self.expected_type = expected_type
13
14 def _matches(self, item):
15 return isinstance(item, self.expected_type)
16
17 def describe_to(self, description):
18 description.append_text('an instance of ') \
19 .append_text(self.expected_type.__name__)
20
21
22 def instance_of(atype):
23 """Matches if object is an instance of, or inherits from, a given type.
24
25 :param atype: The type to compare against as the expected type.
26
27 This matcher checks whether the evaluated object is an instance of
28 ``atype`` or an instance of any class that inherits from ``atype``.
29
30 Example::
31
32 instance_of(str)
33
34 """
35 return IsInstanceOf(atype)
+0
-25
hamcrest/core/core/isnone.py less more
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4 from hamcrest.core.base_matcher import BaseMatcher
5 from isnot import is_not
6
7
8 class IsNone(BaseMatcher):
9
10 def _matches(self, item):
11 return item is None
12
13 def describe_to(self, description):
14 description.append_text('None')
15
16
17 def none():
18 """Matches if object is ``None``."""
19 return IsNone()
20
21
22 def not_none():
23 """Matches if object is not ``None``."""
24 return is_not(none())
+0
-38
hamcrest/core/core/isnot.py less more
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4 from hamcrest.core.base_matcher import BaseMatcher, Matcher
5 from hamcrest.core.helpers.wrap_matcher import wrap_matcher
6 from isequal import equal_to
7
8
9 class IsNot(BaseMatcher):
10
11 def __init__(self, matcher):
12 self.matcher = matcher
13
14 def _matches(self, item):
15 return not self.matcher.matches(item)
16
17 def describe_to(self, description):
18 description.append_text('not ').append_description_of(self.matcher)
19
20
21 def is_not(match):
22 """Inverts the given matcher to its logical negation.
23
24 :param match: The matcher to negate.
25
26 This matcher compares the evaluated object to the negation of the given
27 matcher. If the ``match`` argument is not a matcher, it is implicitly
28 wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to
29 check for equality, and thus matches for inequality.
30
31 Examples::
32
33 assert_that(cheese, is_not(equal_to(smelly)))
34 assert_that(cheese, is_not(smelly))
35
36 """
37 return IsNot(wrap_matcher(match))
+0
-39
hamcrest/core/core/issame.py less more
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4 from hamcrest.core.base_matcher import BaseMatcher
5
6
7 class IsSame(BaseMatcher):
8
9 def __init__(self, object):
10 self.object = object
11
12 def _matches(self, item):
13 return item is self.object
14
15 def describe_to(self, description):
16 description.append_text('same instance as ') \
17 .append_text(hex(id(self.object))) \
18 .append_text(' ') \
19 .append_description_of(self.object)
20
21 def describe_mismatch(self, item, mismatch_description):
22 mismatch_description.append_text('was ')
23 if item is not None:
24 mismatch_description.append_text(hex(id(item))) \
25 .append_text(' ')
26 mismatch_description.append_description_of(item)
27
28
29 def same_instance(obj):
30 """Matches if evaluated object is the same instance as a given object.
31
32 :param obj: The object to compare against as the expected value.
33
34 This matcher invokes the ``is`` identity operator to determine if the
35 evaluated object is the the same object as ``obj``.
36
37 """
38 return IsSame(obj)
+0
-58
hamcrest/core/description.py less more
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4
5 class Description(object):
6 """A description of a :py:class:`~hamcrest.core.matcher.Matcher`.
7
8 A :py:class:`~hamcrest.core.matcher.Matcher` will describe itself to a
9 description which can later be used for reporting.
10
11 """
12
13 def append_text(self, text):
14 """Appends some plain text to the description.
15
16 :returns: ``self``, for chaining
17
18 """
19 raise NotImplementedError('append_text')
20
21 def append_description_of(self, value):
22 """Appends description of given value to this description.
23
24 If the value implements
25 :py:meth:`~hamcrest.core.selfdescribing.SelfDescribing.describe_to`,
26 then it will be used.
27
28 :returns: ``self``, for chaining
29
30 """
31 raise NotImplementedError('append_description_of')
32
33 def append_value(self, value):
34 """Appends an arbitary value to the description.
35
36 **Deprecated:** Call
37 :py:meth:`~hamcrest.core.description.Description.append_description_of`
38 instead.
39
40 :returns: ``self``, for chaining
41
42 """
43 raise NotImplementedError('append_value')
44
45 def append_list(self, start, separator, end, list):
46 """Appends a list of objects to the description.
47
48 :param start: String that will begin the list description.
49 :param separator: String that will separate each object in the
50 description.
51 :param end: String that will end the list description.
52 :param list: List of objects to be described.
53
54 :returns: ``self``, for chaining
55
56 """
57 raise NotImplementedError('append_list')
+0
-5
hamcrest/core/helpers/__init__.py less more
0 """Utilities for writing Matchers."""
1
2 __author__ = "Jon Reid"
3 __copyright__ = "Copyright 2011 hamcrest.org"
4 __license__ = "BSD, see License.txt"
+0
-12
hamcrest/core/helpers/hasmethod.py less more
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4
5 def hasmethod(obj, methodname):
6 """Does ``obj`` have a method named ``methodname``?"""
7
8 if not hasattr(obj, methodname):
9 return False
10 method = getattr(obj, methodname)
11 return callable(method)
+0
-19
hamcrest/core/helpers/wrap_matcher.py less more
0 from hamcrest.core.base_matcher import Matcher
1 from hamcrest.core.core.isequal import equal_to
2
3 __author__ = "Jon Reid"
4 __copyright__ = "Copyright 2011 hamcrest.org"
5 __license__ = "BSD, see License.txt"
6
7
8 def wrap_matcher(x):
9 """Wraps argument in a matcher, if necessary.
10
11 :returns: the argument as-is if it is already a matcher, otherwise wrapped
12 in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher.
13
14 """
15 if isinstance(x, Matcher):
16 return x
17 else:
18 return equal_to(x)
+0
-51
hamcrest/core/matcher.py less more
0 from selfdescribing import SelfDescribing
1
2 __author__ = "Jon Reid"
3 __copyright__ = "Copyright 2011 hamcrest.org"
4 __license__ = "BSD, see License.txt"
5
6
7 class Matcher(SelfDescribing):
8 """A matcher over acceptable values.
9
10 A matcher is able to describe itself to give feedback when it fails.
11
12 Matcher implementations should *not* directly implement this protocol.
13 Instead, *extend* the :py:class:`~hamcrest.core.base_matcher.BaseMatcher`
14 class, which will ensure that the
15 :py:class:`~hamcrest.core.matcher.Matcher` API can grow to support new
16 features and remain compatible with all
17 :py:class:`~hamcrest.core.matcher.Matcher` implementations.
18
19 """
20
21 def matches(self, item, mismatch_description=None):
22 """Evaluates the matcher for argument item.
23
24 If a mismatch is detected and argument ``mismatch_description`` is
25 provided, it will generate a description of why the matcher has not
26 accepted the item.
27
28 :param item: The object against which the matcher is evaluated.
29 :returns: ``True`` if ``item`` matches, otherwise ``False``.
30
31 """
32 raise NotImplementedError('matches')
33
34 def describe_mismatch(self, item, mismatch_description):
35 """Generates a description of why the matcher has not accepted the
36 item.
37
38 The description will be part of a larger description of why a matching
39 failed, so it should be concise.
40
41 This method assumes that ``matches(item)`` is ``False``, but will not
42 check this.
43
44 :param item: The item that the
45 :py:class:`~hamcrest.core.matcher.Matcher` has rejected.
46 :param mismatch_description: The description to be built or appended
47 to.
48
49 """
50 raise NotImplementedError('describe_mismatch')
+0
-18
hamcrest/core/selfdescribing.py less more
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4
5 class SelfDescribing(object):
6 """The ability of an object to describe itself."""
7
8 def describe_to(self, description):
9 """Generates a description of the object.
10
11 The description may be part of a description of a larger object of
12 which this is just a component, so it should be worded appropriately.
13
14 :param description: The description to be built or appended to.
15
16 """
17 raise NotImplementedError('describe_to')
+0
-27
hamcrest/core/selfdescribingvalue.py less more
0 from hamcrest.core.selfdescribing import SelfDescribing
1
2 import warnings
3
4 __author__ = "Jon Reid"
5 __copyright__ = "Copyright 2011 hamcrest.org"
6 __license__ = "BSD, see License.txt"
7
8
9 class SelfDescribingValue(SelfDescribing):
10 """Wrap any value in a ``SelfDescribingValue`` to satisfy the
11 :py:class:`~hamcrest.core.selfdescribing.SelfDescribing` interface.
12
13 **Deprecated:** No need for this class now that
14 :py:meth:`~hamcrest.core.description.Description.append_description_of`
15 handles any type of value.
16
17 """
18
19 def __init__(self, value):
20 warnings.warn('SelfDescribingValue no longer needed',
21 DeprecationWarning)
22 self.value = value
23
24 def describe_to(self, description):
25 """Generates a description of the value."""
26 description.append_value(self.value)
+0
-33
hamcrest/core/string_description.py less more
0 from base_description import BaseDescription
1
2 __author__ = "Jon Reid"
3 __copyright__ = "Copyright 2011 hamcrest.org"
4 __license__ = "BSD, see License.txt"
5
6
7 def tostring(selfdescribing):
8 """Returns the description of a
9 :py:class:`~hamcrest.core.selfdescribing.SelfDescribing` object as a
10 string.
11
12 :param selfdescribing: The object to be described.
13 :returns: The description of the object.
14 """
15 return str(StringDescription().append_description_of(selfdescribing))
16
17
18 class StringDescription(BaseDescription):
19 """A :py:class:`~hamcrest.core.description.Description` that is stored as a
20 string.
21
22 """
23
24 def __init__(self):
25 self.out = ''
26
27 def __str__(self):
28 """Returns the description."""
29 return self.out
30
31 def append(self, string):
32 self.out += string
+0
-39
hamcrest/library/__init__.py less more
0 """Library of Matcher implementations."""
1
2 from hamcrest.core import *
3 from collection import *
4 from integration import *
5 from number import *
6 from object import *
7 from text import *
8
9 __author__ = "Jon Reid"
10 __copyright__ = "Copyright 2011 hamcrest.org"
11 __license__ = "BSD, see License.txt"
12
13 __all__ = [
14 'has_entry',
15 'has_entries',
16 'has_key',
17 'has_value',
18 'is_in',
19 'has_item',
20 'has_items',
21 'contains_inanyorder',
22 'contains',
23 'only_contains',
24 'match_equality',
25 'close_to',
26 'greater_than',
27 'greater_than_or_equal_to',
28 'less_than',
29 'less_than_or_equal_to',
30 'has_length',
31 'has_property',
32 'has_string',
33 'equal_to_ignoring_case',
34 'equal_to_ignoring_whitespace',
35 'contains_string',
36 'ends_with',
37 'starts_with',
38 ]
+0
-15
hamcrest/library/collection/__init__.py less more
0 """Matchers of collections."""
1
2 from isdict_containing import has_entry
3 from isdict_containingentries import has_entries
4 from isdict_containingkey import has_key
5 from isdict_containingvalue import has_value
6 from isin import is_in
7 from issequence_containing import has_item, has_items
8 from issequence_containinginanyorder import contains_inanyorder
9 from issequence_containinginorder import contains
10 from issequence_onlycontaining import only_contains
11
12 __author__ = "Jon Reid"
13 __copyright__ = "Copyright 2011 hamcrest.org"
14 __license__ = "BSD, see License.txt"
+0
-54
hamcrest/library/collection/isdict_containing.py less more
0 from hamcrest.core.base_matcher import BaseMatcher
1 from hamcrest.core.helpers.hasmethod import hasmethod
2 from hamcrest.core.helpers.wrap_matcher import wrap_matcher
3
4 __author__ = "Jon Reid"
5 __copyright__ = "Copyright 2011 hamcrest.org"
6 __license__ = "BSD, see License.txt"
7
8
9 class IsDictContaining(BaseMatcher):
10
11 def __init__(self, key_matcher, value_matcher):
12 self.key_matcher = key_matcher
13 self.value_matcher = value_matcher
14
15 def _matches(self, dictionary):
16 if hasmethod(dictionary, 'items'):
17 for key, value in dictionary.items():
18 if self.key_matcher.matches(key) and self.value_matcher.matches(value):
19 return True
20 return False
21
22 def describe_to(self, description):
23 description.append_text('a dictionary containing [') \
24 .append_description_of(self.key_matcher) \
25 .append_text(': ') \
26 .append_description_of(self.value_matcher) \
27 .append_text(']')
28
29
30 def has_entry(key_match, value_match):
31 """Matches if dictionary contains key-value entry satisfying a given pair
32 of matchers.
33
34 :param key_match: The matcher to satisfy for the key, or an expected value
35 for :py:func:`~hamcrest.core.core.isequal.equal_to` matching.
36 :param value_match: The matcher to satisfy for the value, or an expected
37 value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching.
38
39 This matcher iterates the evaluated dictionary, searching for any key-value
40 entry that satisfies ``key_match`` and ``value_match``. If a matching entry
41 is found, ``has_entry`` is satisfied.
42
43 Any argument that is not a matcher is implicitly wrapped in an
44 :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
45 equality.
46
47 Examples::
48
49 has_entry(equal_to('foo'), equal_to(1))
50 has_entry('foo', 1)
51
52 """
53 return IsDictContaining(wrap_matcher(key_match), wrap_matcher(value_match))
+0
-134
hamcrest/library/collection/isdict_containingentries.py less more
0 from hamcrest.core.base_matcher import BaseMatcher
1 from hamcrest.core.helpers.hasmethod import hasmethod
2 from hamcrest.core.helpers.wrap_matcher import wrap_matcher
3
4 __author__ = "Jon Reid"
5 __copyright__ = "Copyright 2011 hamcrest.org"
6 __license__ = "BSD, see License.txt"
7
8
9 class IsDictContainingEntries(BaseMatcher):
10
11 def __init__(self, value_matchers):
12 self.value_matchers = value_matchers
13
14 def _not_a_dictionary(self, dictionary, mismatch_description):
15 if mismatch_description:
16 mismatch_description.append_description_of(dictionary) \
17 .append_text(' is not a mapping object')
18 return False
19
20 def matches(self, dictionary, mismatch_description=None):
21 for key in self.value_matchers:
22
23 try:
24 if not key in dictionary:
25 if mismatch_description:
26 mismatch_description.append_text('no ') \
27 .append_description_of(key) \
28 .append_text(' key in ') \
29 .append_description_of(dictionary)
30 return False
31 except TypeError:
32 return self._not_a_dictionary(dictionary, mismatch_description)
33
34 value_matcher = self.value_matchers[key]
35 try:
36 actual_value = dictionary[key]
37 except TypeError:
38 return self._not_a_dictionary(dictionary, mismatch_description)
39
40 if not value_matcher.matches(actual_value):
41 if mismatch_description:
42 mismatch_description.append_text('value for ') \
43 .append_description_of(key) \
44 .append_text(' ')
45 value_matcher.describe_mismatch(actual_value, mismatch_description)
46 return False
47
48 return True
49
50 def describe_mismatch(self, item, mismatch_description):
51 self.matches(item, mismatch_description)
52
53 def describe_keyvalue(self, index, description):
54 """Describes key-value pair at given index."""
55 description.append_description_of(index) \
56 .append_text(': ') \
57 .append_description_of(self.value_matchers[index])
58
59 def describe_to(self, description):
60 description.append_text('a dictionary containing {')
61 first = True
62 for key in self.value_matchers:
63 if not first:
64 description.append_text(', ')
65 self.describe_keyvalue(key, description)
66 first = False
67 description.append_text('}')
68
69
70 def has_entries(*keys_valuematchers, **kv_args):
71 """Matches if dictionary contains entries satisfying a dictionary of keys
72 and corresponding value matchers.
73
74 :param matcher_dict: A dictionary mapping keys to associated value matchers,
75 or to expected values for
76 :py:func:`~hamcrest.core.core.isequal.equal_to` matching.
77
78 Note that the keys must be actual keys, not matchers. Any value argument
79 that is not a matcher is implicitly wrapped in an
80 :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
81 equality.
82
83 Examples::
84
85 has_entries({'foo':equal_to(1), 'bar':equal_to(2)})
86 has_entries({'foo':1, 'bar':2})
87
88 ``has_entries`` also accepts a list of keyword arguments:
89
90 .. function:: has_entries(keyword1=value_matcher1[, keyword2=value_matcher2[, ...]])
91
92 :param keyword1: A keyword to look up.
93 :param valueMatcher1: The matcher to satisfy for the value, or an expected
94 value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching.
95
96 Examples::
97
98 has_entries(foo=equal_to(1), bar=equal_to(2))
99 has_entries(foo=1, bar=2)
100
101 Finally, ``has_entries`` also accepts a list of alternating keys and their
102 value matchers:
103
104 .. function:: has_entries(key1, value_matcher1[, ...])
105
106 :param key1: A key (not a matcher) to look up.
107 :param valueMatcher1: The matcher to satisfy for the value, or an expected
108 value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching.
109
110 Examples::
111
112 has_entries('foo', equal_to(1), 'bar', equal_to(2))
113 has_entries('foo', 1, 'bar', 2)
114
115 """
116 if len(keys_valuematchers) == 1:
117 try:
118 base_dict = keys_valuematchers[0].copy()
119 for key in base_dict:
120 base_dict[key] = wrap_matcher(base_dict[key])
121 except AttributeError:
122 raise ValueError('single-argument calls to has_entries must pass a dict as the argument')
123 else:
124 if len(keys_valuematchers) % 2:
125 raise ValueError('has_entries requires key-value pairs')
126 base_dict = {}
127 for index in range(int(len(keys_valuematchers) / 2)):
128 base_dict[keys_valuematchers[2 * index]] = wrap_matcher(keys_valuematchers[2 * index + 1])
129
130 for key, value in kv_args.items():
131 base_dict[key] = wrap_matcher(value)
132
133 return IsDictContainingEntries(base_dict)
+0
-48
hamcrest/library/collection/isdict_containingkey.py less more
0 from hamcrest.core.base_matcher import BaseMatcher
1 from hamcrest.core.helpers.hasmethod import hasmethod
2 from hamcrest.core.helpers.wrap_matcher import wrap_matcher
3
4 __author__ = "Jon Reid"
5 __copyright__ = "Copyright 2011 hamcrest.org"
6 __license__ = "BSD, see License.txt"
7
8
9 class IsDictContainingKey(BaseMatcher):
10
11 def __init__(self, key_matcher):
12 self.key_matcher = key_matcher
13
14 def _matches(self, dictionary):
15 if hasmethod(dictionary, 'keys'):
16 for key in dictionary.keys():
17 if self.key_matcher.matches(key):
18 return True
19 return False
20
21 def describe_to(self, description):
22 description.append_text('a dictionary containing key ') \
23 .append_description_of(self.key_matcher)
24
25
26 def has_key(key_match):
27 """Matches if dictionary contains an entry whose key satisfies a given
28 matcher.
29
30 :param key_match: The matcher to satisfy for the key, or an expected value
31 for :py:func:`~hamcrest.core.core.isequal.equal_to` matching.
32
33 This matcher iterates the evaluated dictionary, searching for any key-value
34 entry whose key satisfies the given matcher. If a matching entry is found,
35 ``has_key`` is satisfied.
36
37 Any argument that is not a matcher is implicitly wrapped in an
38 :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
39 equality.
40
41 Examples::
42
43 has_key(equal_to('foo'))
44 has_key('foo')
45
46 """
47 return IsDictContainingKey(wrap_matcher(key_match))
+0
-48
hamcrest/library/collection/isdict_containingvalue.py less more
0 from hamcrest.core.base_matcher import BaseMatcher
1 from hamcrest.core.helpers.hasmethod import hasmethod
2 from hamcrest.core.helpers.wrap_matcher import wrap_matcher
3
4 __author__ = "Jon Reid"
5 __copyright__ = "Copyright 2011 hamcrest.org"
6 __license__ = "BSD, see License.txt"
7
8
9 class IsDictContainingValue(BaseMatcher):
10
11 def __init__(self, value_matcher):
12 self.value_matcher = value_matcher
13
14 def _matches(self, dictionary):
15 if hasmethod(dictionary, 'values'):
16 for value in dictionary.values():
17 if self.value_matcher.matches(value):
18 return True
19 return False
20
21 def describe_to(self, description):
22 description.append_text('a dictionary containing value ') \
23 .append_description_of(self.value_matcher)
24
25
26 def has_value(value):
27 """Matches if dictionary contains an entry whose value satisfies a given
28 matcher.
29
30 :param value_match: The matcher to satisfy for the value, or an expected
31 value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching.
32
33 This matcher iterates the evaluated dictionary, searching for any key-value
34 entry whose value satisfies the given matcher. If a matching entry is
35 found, ``has_value`` is satisfied.
36
37 Any argument that is not a matcher is implicitly wrapped in an
38 :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
39 equality.
40
41 Examples::
42
43 has_value(equal_to('bar'))
44 has_value('bar')
45
46 """
47 return IsDictContainingValue(wrap_matcher(value))
+0
-30
hamcrest/library/collection/isin.py less more
0 from hamcrest.core.base_matcher import BaseMatcher
1
2 __author__ = "Jon Reid"
3 __copyright__ = "Copyright 2011 hamcrest.org"
4 __license__ = "BSD, see License.txt"
5
6
7 class IsIn(BaseMatcher):
8
9 def __init__(self, sequence):
10 self.sequence = sequence
11
12 def _matches(self, item):
13 return item in self.sequence
14
15 def describe_to(self, description):
16 description.append_text('one of ') \
17 .append_list('(', ', ', ')', self.sequence)
18
19
20 def is_in(sequence):
21 """Matches if evaluated object is present in a given sequence.
22
23 :param sequence: The sequence to search.
24
25 This matcher invokes the ``in`` membership operator to determine if the
26 evaluated object is a member of the sequence.
27
28 """
29 return IsIn(sequence)
+0
-64
hamcrest/library/collection/issequence_containing.py less more
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4 from hamcrest.core.base_matcher import BaseMatcher
5 from hamcrest.core.core.allof import all_of
6 from hamcrest.core.helpers.hasmethod import hasmethod
7 from hamcrest.core.helpers.wrap_matcher import wrap_matcher
8
9
10 class IsSequenceContaining(BaseMatcher):
11
12 def __init__(self, element_matcher):
13 self.element_matcher = element_matcher
14
15 def _matches(self, sequence):
16 if hasmethod(sequence, '__iter__'):
17 for item in sequence:
18 if self.element_matcher.matches(item):
19 return True
20 return False
21
22 def describe_to(self, description):
23 description.append_text('a sequence containing ') \
24 .append_description_of(self.element_matcher)
25
26
27 def has_item(match):
28 """Matches if any element of sequence satisfies a given matcher.
29
30 :param match: The matcher to satisfy, or an expected value for
31 :py:func:`~hamcrest.core.core.isequal.equal_to` matching.
32
33 This matcher iterates the evaluated sequence, searching for any element
34 that satisfies a given matcher. If a matching element is found,
35 ``has_item`` is satisfied.
36
37 If the ``match`` argument is not a matcher, it is implicitly wrapped in an
38 :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
39 equality.
40
41 """
42 return IsSequenceContaining(wrap_matcher(match))
43
44
45 def has_items(*items):
46 """Matches if all of the given matchers are satisfied by any elements of
47 the sequence.
48
49 :param match1,...: A comma-separated list of matchers.
50
51 This matcher iterates the given matchers, searching for any elements in the
52 evaluated sequence that satisfy them. If each matcher is satisfied, then
53 ``has_items`` is satisfied.
54
55 Any argument that is not a matcher is implicitly wrapped in an
56 :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
57 equality.
58
59 """
60 matchers = []
61 for item in items:
62 matchers.append(has_item(item))
63 return apply(all_of, matchers)
+0
-96
hamcrest/library/collection/issequence_containinginanyorder.py less more
0 from hamcrest.core.base_matcher import BaseMatcher
1 from hamcrest.core.helpers.hasmethod import hasmethod
2 from hamcrest.core.helpers.wrap_matcher import wrap_matcher
3
4 __author__ = "Jon Reid"
5 __copyright__ = "Copyright 2011 hamcrest.org"
6 __license__ = "BSD, see License.txt"
7
8
9 class MatchInAnyOrder(object):
10 def __init__(self, matchers, mismatch_description):
11 self.matchers = matchers
12 self.mismatch_description = mismatch_description
13
14 def matches(self, item):
15 return self.isnotsurplus(item) and self.ismatched(item)
16
17 def isfinished(self, sequence):
18 if not self.matchers:
19 return True
20 if self.mismatch_description:
21 self.mismatch_description.append_text('no item matches: ') \
22 .append_list('', ', ', '', self.matchers) \
23 .append_text(' in ') \
24 .append_list('[', ', ', ']', sequence)
25 return False
26
27 def isnotsurplus(self, item):
28 if not self.matchers:
29 if self.mismatch_description:
30 self.mismatch_description.append_text('not matched: ') \
31 .append_description_of(item)
32 return False
33 return True
34
35 def ismatched(self, item):
36 index = 0
37 for matcher in self.matchers:
38 if matcher.matches(item):
39 del self.matchers[index]
40 return True
41 index += 1
42 if self.mismatch_description:
43 self.mismatch_description.append_text('not matched: ') \
44 .append_description_of(item)
45 return False
46
47
48 class IsSequenceContainingInAnyOrder(BaseMatcher):
49
50 def __init__(self, matchers):
51 self.matchers = matchers
52
53 def matches(self, sequence, mismatch_description=None):
54 if not hasmethod(sequence, '__iter__'):
55 if mismatch_description:
56 super(IsSequenceContainingInAnyOrder, self) \
57 .describe_mismatch(sequence, mismatch_description)
58 return False
59 matchsequence = MatchInAnyOrder(self.matchers, mismatch_description)
60 for item in sequence:
61 if not matchsequence.matches(item):
62 return False
63 return matchsequence.isfinished(sequence)
64
65 def describe_mismatch(self, item, mismatch_description):
66 self.matches(item, mismatch_description)
67
68 def describe_to(self, description):
69 description.append_text('a sequence over ') \
70 .append_list('[', ', ', ']', self.matchers) \
71 .append_text(' in any order')
72
73
74 def contains_inanyorder(*items):
75 """Matches if sequences's elements, in any order, satisfy a given list of
76 matchers.
77
78 :param match1,...: A comma-separated list of matchers.
79
80 This matcher iterates the evaluated sequence, seeing if each element
81 satisfies any of the given matchers. The matchers are tried from left to
82 right, and when a satisfied matcher is found, it is no longer a candidate
83 for the remaining elements. If a one-to-one correspondence is established
84 between elements and matchers, ``contains_inanyorder`` is satisfied.
85
86 Any argument that is not a matcher is implicitly wrapped in an
87 :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
88 equality.
89
90 """
91
92 matchers = []
93 for item in items:
94 matchers.append(wrap_matcher(item))
95 return IsSequenceContainingInAnyOrder(matchers)
+0
-87
hamcrest/library/collection/issequence_containinginorder.py less more
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4 from hamcrest.core.base_matcher import BaseMatcher
5 from hamcrest.core.helpers.hasmethod import hasmethod
6 from hamcrest.core.helpers.wrap_matcher import wrap_matcher
7
8
9 class MatchingInOrder(object):
10 def __init__(self, matchers, mismatch_description):
11 self.matchers = matchers
12 self.mismatch_description = mismatch_description
13 self.next_match_index = 0
14
15 def matches(self, item):
16 return self.isnotsurplus(item) and self.ismatched(item)
17
18 def isfinished(self):
19 if self.next_match_index < len(self.matchers):
20 if self.mismatch_description:
21 self.mismatch_description.append_text('No item matched: ') \
22 .append_description_of(self.matchers[self.next_match_index])
23 return False
24 return True
25
26 def ismatched(self, item):
27 matcher = self.matchers[self.next_match_index]
28 if not matcher.matches(item):
29 if self.mismatch_description:
30 self.mismatch_description.append_text('item ' + str(self.next_match_index) + ': ')
31 matcher.describe_mismatch(item, self.mismatch_description)
32 return False
33 self.next_match_index += 1
34 return True
35
36 def isnotsurplus(self, item):
37 if len(self.matchers) <= self.next_match_index:
38 if self.mismatch_description:
39 self.mismatch_description.append_text('Not matched: ') \
40 .append_description_of(item)
41 return False
42 return True
43
44
45 class IsSequenceContainingInOrder(BaseMatcher):
46
47 def __init__(self, matchers):
48 self.matchers = matchers
49
50 def matches(self, sequence, mismatch_description=None):
51 if not hasmethod(sequence, '__iter__'):
52 if mismatch_description:
53 super(IsSequenceContainingInOrder, self) \
54 .describe_mismatch(sequence, mismatch_description)
55 return False
56 matchsequence = MatchingInOrder(self.matchers, mismatch_description)
57 for item in sequence:
58 if not matchsequence.matches(item):
59 return False
60 return matchsequence.isfinished()
61
62 def describe_mismatch(self, item, mismatch_description):
63 self.matches(item, mismatch_description)
64
65 def describe_to(self, description):
66 description.append_text('a sequence containing ') \
67 .append_list('[', ', ', ']', self.matchers)
68
69
70 def contains(*items):
71 """Matches if sequence's elements satisfy a given list of matchers, in order.
72
73 :param match1,...: A comma-separated list of matchers.
74
75 This matcher iterates the evaluated sequence and a given list of matchers,
76 seeing if each element satisfies its corresponding matcher.
77
78 Any argument that is not a matcher is implicitly wrapped in an
79 :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
80 equality.
81
82 """
83 matchers = []
84 for item in items:
85 matchers.append(wrap_matcher(item))
86 return IsSequenceContainingInOrder(matchers)
+0
-55
hamcrest/library/collection/issequence_onlycontaining.py less more
0 from hamcrest.core.base_matcher import BaseMatcher
1 from hamcrest.core.core.anyof import any_of
2 from hamcrest.core.helpers.hasmethod import hasmethod
3 from hamcrest.core.helpers.wrap_matcher import wrap_matcher
4
5 __author__ = "Jon Reid"
6 __copyright__ = "Copyright 2011 hamcrest.org"
7 __license__ = "BSD, see License.txt"
8
9
10 class IsSequenceOnlyContaining(BaseMatcher):
11
12 def __init__(self, matcher):
13 self.matcher = matcher
14
15 def _matches(self, sequence):
16 if not hasmethod(sequence, '__len__') \
17 or not hasmethod(sequence, '__iter__'):
18 return False
19
20 if len(sequence) == 0:
21 return False
22 for item in sequence:
23 if not self.matcher.matches(item):
24 return False
25 return True
26
27 def describe_to(self, description):
28 description.append_text('a sequence containing items matching ') \
29 .append_description_of(self.matcher)
30
31
32 def only_contains(*items):
33 """Matches if each element of sequence satisfies any of the given matchers.
34
35 :param match1,...: A comma-separated list of matchers.
36
37 This matcher iterates the evaluated sequence, confirming whether each
38 element satisfies any of the given matchers.
39
40 Example::
41
42 only_contains(less_than(4))
43
44 will match ``[3,1,2]``.
45
46 Any argument that is not a matcher is implicitly wrapped in an
47 :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
48 equality.
49
50 """
51 matchers = []
52 for item in items:
53 matchers.append(wrap_matcher(item))
54 return IsSequenceOnlyContaining(apply(any_of, matchers))
+0
-7
hamcrest/library/integration/__init__.py less more
0 """Utilities for integrating Hamcrest with other libraries."""
1
2 from match_equality import match_equality
3
4 __author__ = "Jon Reid"
5 __copyright__ = "Copyright 2011 hamcrest.org"
6 __license__ = "BSD, see License.txt"
+0
-42
hamcrest/library/integration/match_equality.py less more
0 from hamcrest.core.string_description import tostring
1 from hamcrest.core.helpers.wrap_matcher import wrap_matcher
2
3 __author__ = "Chris Rose"
4 __copyright__ = "Copyright 2011 hamcrest.org"
5 __license__ = "BSD, see License.txt"
6 __unittest = True
7
8
9 class EqualityWrapper(object):
10
11 def __init__(self, matcher):
12 self.matcher = matcher
13
14 def __eq__(self, object):
15 return self.matcher.matches(object)
16
17 def __str__(self):
18 return repr(self)
19
20 def __repr__(self):
21 return tostring(self.matcher)
22
23
24 def match_equality(matcher):
25 """Wraps a matcher to define equality in terms of satisfying the matcher.
26
27 ``match_equality`` allows Hamcrest matchers to be used in libraries that
28 are not Hamcrest-aware. They might use the equality operator::
29
30 assert match_equality(matcher) == object
31
32 Or they might provide a method that uses equality for its test::
33
34 library.method_that_tests_eq(match_equality(matcher))
35
36 One concrete example is integrating with the ``assert_called_with`` methods
37 in Michael Foord's `mock <http://www.voidspace.org.uk/python/mock/>`_
38 library.
39
40 """
41 return EqualityWrapper(wrap_matcher(matcher))
+0
-8
hamcrest/library/number/__init__.py less more
0 """Matchers that perform numeric comparisons."""
1
2 from iscloseto import close_to
3 from ordering_comparison import greater_than, greater_than_or_equal_to, less_than, less_than_or_equal_to
4
5 __author__ = "Jon Reid"
6 __copyright__ = "Copyright 2011 hamcrest.org"
7 __license__ = "BSD, see License.txt"
+0
-61
hamcrest/library/number/iscloseto.py less more
0 from hamcrest.core.base_matcher import BaseMatcher
1 from math import fabs
2
3 __author__ = "Jon Reid"
4 __copyright__ = "Copyright 2011 hamcrest.org"
5 __license__ = "BSD, see License.txt"
6
7
8 def isnumeric(value):
9 return isinstance(value, (int, long, float))
10
11
12 class IsCloseTo(BaseMatcher):
13
14 def __init__(self, value, delta):
15 if not isnumeric(value):
16 raise TypeError('IsCloseTo value must be numeric')
17 if not isnumeric(delta):
18 raise TypeError('IsCloseTo delta must be numeric')
19
20 self.value = value
21 self.delta = delta
22
23 def _matches(self, item):
24 if not isnumeric(item):
25 return False
26 return fabs(item - self.value) <= self.delta
27
28 def describe_mismatch(self, item, mismatch_description):
29 if not isnumeric(item):
30 super(IsCloseTo, self).describe_mismatch(item, mismatch_description)
31 else:
32 actual_delta = fabs(item - self.value)
33 mismatch_description.append_description_of(item) \
34 .append_text(' differed by ') \
35 .append_description_of(actual_delta)
36
37 def describe_to(self, description):
38 description.append_text('a numeric value within ') \
39 .append_description_of(self.delta) \
40 .append_text(' of ') \
41 .append_description_of(self.value)
42
43
44 def close_to(value, delta):
45 """Matches if object is a number close to a given value, within a given
46 delta.
47
48 :param value: The value to compare against as the expected value.
49 :param delta: The maximum delta between the values for which the numbers
50 are considered close.
51
52 This matcher compares the evaluated object against ``value`` to see if the
53 difference is within a positive ``delta``.
54
55 Example::
56
57 close_to(3.0, 0.25)
58
59 """
60 return IsCloseTo(value, delta)
+0
-59
hamcrest/library/number/ordering_comparison.py less more
0 from hamcrest.core.base_matcher import BaseMatcher
1 import operator
2
3 __author__ = "Jon Reid"
4 __copyright__ = "Copyright 2011 hamcrest.org"
5 __license__ = "BSD, see License.txt"
6
7
8 class OrderingComparison(BaseMatcher):
9
10 def __init__(self, value, comparison_function, comparison_description):
11 self.value = value
12 self.comparison_function = comparison_function
13 self.comparison_description = comparison_description
14
15 def _matches(self, item):
16 return self.comparison_function(item, self.value)
17
18 def describe_to(self, description):
19 description.append_text('a value ') \
20 .append_text(self.comparison_description) \
21 .append_text(' ') \
22 .append_description_of(self.value)
23
24
25 def greater_than(value):
26 """Matches if object is greater than a given value.
27
28 :param value: The value to compare against.
29
30 """
31 return OrderingComparison(value, operator.gt, 'greater than')
32
33
34 def greater_than_or_equal_to(value):
35 """Matches if object is greater than or equal to a given value.
36
37 :param value: The value to compare against.
38
39 """
40 return OrderingComparison(value, operator.ge, 'greater than or equal to')
41
42
43 def less_than(value):
44 """Matches if object is less than a given value.
45
46 :param value: The value to compare against.
47
48 """
49 return OrderingComparison(value, operator.lt, 'less than')
50
51
52 def less_than_or_equal_to(value):
53 """Matches if object is less than or equal to a given value.
54
55 :param value: The value to compare against.
56
57 """
58 return OrderingComparison(value, operator.le, 'less than or equal to')
+0
-9
hamcrest/library/object/__init__.py less more
0 """Matchers that inspect objects and classes."""
1
2 from haslength import has_length
3 from hasproperty import has_property
4 from hasstring import has_string
5
6 __author__ = "Jon Reid"
7 __copyright__ = "Copyright 2011 hamcrest.org"
8 __license__ = "BSD, see License.txt"
+0
-50
hamcrest/library/object/haslength.py less more
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4 from hamcrest.core.base_matcher import BaseMatcher
5 from hamcrest.core.helpers.hasmethod import hasmethod
6 from hamcrest.core.helpers.wrap_matcher import wrap_matcher
7
8
9 class HasLength(BaseMatcher):
10
11 def __init__(self, len_matcher):
12 self.len_matcher = len_matcher
13
14 def _matches(self, item):
15 if not hasmethod(item, '__len__'):
16 return False
17 return self.len_matcher.matches(len(item))
18
19 def describe_mismatch(self, item, mismatch_description):
20 super(HasLength, self).describe_mismatch(item, mismatch_description)
21 if hasmethod(item, '__len__'):
22 mismatch_description.append_text(' with length of ') \
23 .append_description_of(len(item))
24
25 def describe_to(self, description):
26 description.append_text('an object with length of ') \
27 .append_description_of(self.len_matcher)
28
29
30 def has_length(match):
31 """Matches if ``len(item)`` satisfies a given matcher.
32
33 :param match: The matcher to satisfy, or an expected value for
34 :py:func:`~hamcrest.core.core.isequal.equal_to` matching.
35
36 This matcher invokes the :py:func:`len` function on the evaluated object to
37 get its length, passing the result to a given matcher for evaluation.
38
39 If the ``match`` argument is not a matcher, it is implicitly wrapped in an
40 :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
41 :equality.
42
43 Examples::
44
45 has_length(greater_than(6))
46 has_length(5)
47
48 """
49 return HasLength(wrap_matcher(match))
+0
-86
hamcrest/library/object/hasproperty.py less more
0 from hamcrest.core.base_matcher import BaseMatcher
1 from hamcrest.core import anything
2 from hamcrest.core.string_description import StringDescription
3 from hamcrest.core.helpers.hasmethod import hasmethod
4 from hamcrest.core.helpers.wrap_matcher import wrap_matcher as wrap_shortcut
5
6 __author__ = "Chris Rose"
7 __copyright__ = "Copyright 2011 hamcrest.org"
8 __license__ = "BSD, see License.txt"
9
10
11 class IsObjectWithProperty(BaseMatcher):
12
13 def __init__(self, property_name, value_matcher):
14 self.property_name = property_name
15 self.value_matcher = value_matcher
16
17 def _matches(self, o):
18 if o is None:
19 return False
20
21 if not hasattr(o, self.property_name):
22 return False
23
24 value = getattr(o, self.property_name)
25 return self.value_matcher.matches(value)
26
27 def describe_to(self, description):
28 description.append_text("an object with a property '") \
29 .append_text(self.property_name) \
30 .append_text("' matching ") \
31 .append_description_of(self.value_matcher)
32
33 def describe_mismatch(self, item, mismatch_description):
34 if item is None:
35 mismatch_description.append_text('was None')
36 return
37
38 if not hasattr(item, self.property_name):
39 mismatch_description.append_value(item) \
40 .append_text(' did not have the ') \
41 .append_value(self.property_name) \
42 .append_text(' property')
43 return
44
45 mismatch_description.append_text('property ').append_value(self.property_name).append_text(' ')
46 value = getattr(item, self.property_name)
47 self.value_matcher.describe_mismatch(value, mismatch_description)
48
49 def __str__(self):
50 d = StringDescription()
51 self.describe_to(d)
52 return str(d)
53
54
55 def has_property(name, match=None):
56 """Matches if object has a property with a given name whose value satisfies
57 a given matcher.
58
59 :param name: The name of the property.
60 :param match: Optional matcher to satisfy.
61
62 This matcher determines if the evaluated object has a property with a given
63 name. If no such property is found, ``has_property`` is not satisfied.
64
65 If the property is found, its value is passed to a given matcher for
66 evaluation. If the ``match`` argument is not a matcher, it is implicitly
67 wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to
68 check for equality.
69
70 If the ``match`` argument is not provided, the
71 :py:func:`~hamcrest.core.core.isanything.anything` matcher is used so that
72 ``has_property`` is satisfied if a matching property is found.
73
74 Examples::
75
76 has_property('name', starts_with('J'))
77 has_property('name', 'Jon')
78 has_property('name')
79
80 """
81
82 if match is None:
83 match = anything()
84
85 return IsObjectWithProperty(name, wrap_shortcut(match))
+0
-40
hamcrest/library/object/hasstring.py less more
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4 from hamcrest.core.base_matcher import BaseMatcher
5 from hamcrest.core.helpers.wrap_matcher import wrap_matcher
6
7
8 class HasString(BaseMatcher):
9
10 def __init__(self, str_matcher):
11 self.str_matcher = str_matcher
12
13 def _matches(self, item):
14 return self.str_matcher.matches(str(item))
15
16 def describe_to(self, description):
17 description.append_text('an object with str ') \
18 .append_description_of(self.str_matcher)
19
20
21 def has_string(match):
22 """Matches if ``str(item)`` satisfies a given matcher.
23
24 :param match: The matcher to satisfy, or an expected value for
25 :py:func:`~hamcrest.core.core.isequal.equal_to` matching.
26
27 This matcher invokes the :py:func:`str` function on the evaluated object to
28 get its length, passing the result to a given matcher for evaluation. If
29 the ``match`` argument is not a matcher, it is implicitly wrapped in an
30 :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
31 equality.
32
33 Examples::
34
35 has_string(starts_with('foo'))
36 has_string('bar')
37
38 """
39 return HasString(wrap_matcher(match))
+0
-11
hamcrest/library/text/__init__.py less more
0 """Matchers that perform text comparisons."""
1
2 from isequal_ignoring_case import equal_to_ignoring_case
3 from isequal_ignoring_whitespace import equal_to_ignoring_whitespace
4 from stringcontains import contains_string
5 from stringendswith import ends_with
6 from stringstartswith import starts_with
7
8 __author__ = "Jon Reid"
9 __copyright__ = "Copyright 2011 hamcrest.org"
10 __license__ = "BSD, see License.txt"
+0
-42
hamcrest/library/text/isequal_ignoring_case.py less more
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4 from hamcrest.core.base_matcher import BaseMatcher
5
6
7 class IsEqualIgnoringCase(BaseMatcher):
8
9 def __init__(self, string):
10 if not isinstance(string, basestring):
11 raise TypeError('IsEqualIgnoringCase requires string')
12 self.original_string = string
13 self.lowered_string = string.lower()
14
15 def _matches(self, item):
16 if not isinstance(item, basestring):
17 return False
18 return self.lowered_string == item.lower()
19
20 def describe_to(self, description):
21 description.append_description_of(self.original_string) \
22 .append_text(' ignoring case')
23
24
25 def equal_to_ignoring_case(string):
26 """Matches if object is a string equal to a given string, ignoring case
27 differences.
28
29 :param string: The string to compare against as the expected value.
30
31 This matcher first checks whether the evaluated object is a string. If so,
32 it compares it with ``string``, ignoring differences of case.
33
34 Example::
35
36 equal_to_ignoring_case("hello world")
37
38 will match "heLLo WorlD".
39
40 """
41 return IsEqualIgnoringCase(string)
+0
-56
hamcrest/library/text/isequal_ignoring_whitespace.py less more
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4 from hamcrest.core.base_matcher import BaseMatcher
5
6
7 def stripspace(string):
8 result = ''
9 last_was_space = True
10 for character in string:
11 if character.isspace():
12 if not last_was_space:
13 result += ' '
14 last_was_space = True
15 else:
16 result += character
17 last_was_space = False
18 return result.strip()
19
20
21 class IsEqualIgnoringWhiteSpace(BaseMatcher):
22
23 def __init__(self, string):
24 if not isinstance(string, basestring):
25 raise TypeError('IsEqualIgnoringWhiteSpace requires string')
26 self.original_string = string
27 self.stripped_string = stripspace(string)
28
29 def _matches(self, item):
30 if not isinstance(item, basestring):
31 return False
32 return self.stripped_string == stripspace(item)
33
34 def describe_to(self, description):
35 description.append_description_of(self.original_string) \
36 .append_text(' ignoring whitespace')
37
38
39 def equal_to_ignoring_whitespace(string):
40 """Matches if object is a string equal to a given string, ignoring
41 differences in whitespace.
42
43 :param string: The string to compare against as the expected value.
44
45 This matcher first checks whether the evaluated object is a string. If so,
46 it compares it with ``string``, ignoring differences in runs of whitespace.
47
48 Example::
49
50 equal_to_ignoring_case("hello world")
51
52 will match ``"hello world"``.
53
54 """
55 return IsEqualIgnoringWhiteSpace(string)
+0
-38
hamcrest/library/text/stringcontains.py less more
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4 from hamcrest.library.text.substringmatcher import SubstringMatcher
5 from hamcrest.core.helpers.hasmethod import hasmethod
6
7
8 class StringContains(SubstringMatcher):
9
10 def __init__(self, substring):
11 super(StringContains, self).__init__(substring)
12
13 def _matches(self, item):
14 if not hasmethod(item, 'find'):
15 return False
16 return item.find(self.substring) >= 0
17
18 def relationship(self):
19 return 'containing'
20
21
22 def contains_string(substring):
23 """Matches if object is a string containing a given string.
24
25 :param string: The string to search for.
26
27 This matcher first checks whether the evaluated object is a string. If so,
28 it checks whether it contains ``string``.
29
30 Example::
31
32 contains_string("def")
33
34 will match "abcdefg".
35
36 """
37 return StringContains(substring)
+0
-51
hamcrest/library/text/stringcontainsinorder.py less more
0 from hamcrest.core.base_matcher import BaseMatcher
1 from hamcrest.core.helpers.hasmethod import hasmethod
2
3 __author__ = "Romilly Cocking"
4 __copyright__ = "Copyright 2011 hamcrest.org"
5 __license__ = "BSD, see License.txt"
6
7
8 class StringContainsInOrder(BaseMatcher):
9
10 def __init__(self, *substrings):
11 for substring in substrings:
12 if not isinstance(substring, basestring):
13 raise TypeError(self.__class__.__name__
14 + ' requires string arguments')
15 self.substrings = substrings
16
17 def _matches(self, item):
18 if not hasmethod(item, 'find'):
19 return False
20 from_index = 0
21 for substring in self.substrings:
22 from_index = item.find(substring, from_index)
23 if from_index == -1:
24 return False
25 return True
26
27 def describe_to(self, description):
28 description.append_list('a string containing ', ', ', ' in order',
29 self.substrings)
30
31
32 def string_contains_in_order(*substrings):
33 """Matches if object is a string containing a given list of substrings in
34 relative order.
35
36 :param string1,...: A comma-separated list of strings.
37
38 This matcher first checks whether the evaluated object is a string. If so,
39 it checks whether it contains a given list of strings, in relative order to
40 each other. The searches are performed starting from the beginning of the
41 evaluated string.
42
43 Example::
44
45 string_contains_in_order("bc", "fg", "jkl")
46
47 will match "abcdefghijklm".
48
49 """
50 return StringContainsInOrder(*substrings)
+0
-39
hamcrest/library/text/stringendswith.py less more
0 from hamcrest.library.text.substringmatcher import SubstringMatcher
1 from hamcrest.core.helpers.hasmethod import hasmethod
2
3 __author__ = "Jon Reid"
4 __copyright__ = "Copyright 2011 hamcrest.org"
5 __license__ = "BSD, see License.txt"
6
7
8 class StringEndsWith(SubstringMatcher):
9
10 def __init__(self, substring):
11 super(StringEndsWith, self).__init__(substring)
12
13 def _matches(self, item):
14 if not hasmethod(item, 'endswith'):
15 return False
16 return item.endswith(self.substring)
17
18 def relationship(self):
19 return 'ending with'
20
21
22 def ends_with(string):
23 """Matches if object is a string ending with a given string.
24
25 :param string: The string to search for.
26
27 This matcher first checks whether the evaluated object is a string. If so,
28 it checks if ``string`` matches the ending characters of the evaluated
29 object.
30
31 Example::
32
33 ends_with("bar")
34
35 will match "foobar".
36
37 """
38 return StringEndsWith(string)
+0
-39
hamcrest/library/text/stringstartswith.py less more
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4 from hamcrest.library.text.substringmatcher import SubstringMatcher
5 from hamcrest.core.helpers.hasmethod import hasmethod
6
7
8 class StringStartsWith(SubstringMatcher):
9
10 def __init__(self, substring):
11 super(StringStartsWith, self).__init__(substring)
12
13 def _matches(self, item):
14 if not hasmethod(item, 'startswith'):
15 return False
16 return item.startswith(self.substring)
17
18 def relationship(self):
19 return 'starting with'
20
21
22 def starts_with(substring):
23 """Matches if object is a string starting with a given string.
24
25 :param string: The string to search for.
26
27 This matcher first checks whether the evaluated object is a string. If so,
28 it checks if ``string`` matches the beginning characters of the evaluated
29 object.
30
31 Example::
32
33 starts_with("foo")
34
35 will match "foobar".
36
37 """
38 return StringStartsWith(substring)
+0
-19
hamcrest/library/text/substringmatcher.py less more
0 from hamcrest.core.base_matcher import BaseMatcher
1
2 __author__ = "Jon Reid"
3 __copyright__ = "Copyright 2011 hamcrest.org"
4 __license__ = "BSD, see License.txt"
5
6
7 class SubstringMatcher(BaseMatcher):
8
9 def __init__(self, substring):
10 if not isinstance(substring, basestring):
11 raise TypeError(self.__class__.__name__ + ' requires string')
12 self.substring = substring
13
14 def describe_to(self, description):
15 description.append_text('a string ') \
16 .append_text(self.relationship()) \
17 .append_text(' ') \
18 .append_description_of(self.substring)
+0
-12
hamcrest_unit_test/__init__.py less more
0 import logging
1 logging.basicConfig()
2
3 from alltests import alltests
4
5 __author__ = "Jon Reid"
6 __copyright__ = "Copyright 2011 hamcrest.org"
7 __license__ = "BSD, see License.txt"
8
9
10 def additional_tests():
11 return alltests()
+0
-32
hamcrest_unit_test/alltests.py less more
0 import os
1 import sys
2 import unittest
3
4 __author__ = "Jon Reid"
5 __copyright__ = "Copyright 2011 hamcrest.org"
6 __license__ = "BSD, see License.txt"
7
8 if __name__ == "__main__":
9 sys.path.insert(0, '..')
10
11
12 def alltests():
13 """Returns suite of all tests in this directory and below."""
14 testloader = unittest.defaultTestLoader
15 suite = testloader.suiteClass()
16
17 fullpath = os.path.abspath(os.path.dirname(sys.argv[0]))
18 for dirpath, dirnames, filenames in os.walk(fullpath):
19 sys.path.insert(0, dirpath)
20 for file in filenames:
21 if file.endswith('test.py'):
22 (name, ext) = os.path.splitext(file)
23 module = __import__(name)
24 suite.addTest(testloader.loadTestsFromModule(module))
25 sys.path.pop(0)
26
27 return suite
28
29
30 if __name__ == '__main__':
31 unittest.main(defaultTest='alltests')
+0
-69
hamcrest_unit_test/assert_that_test.py less more
0 if __name__ == "__main__":
1 import sys
2 sys.path.insert(0, '..')
3
4 from hamcrest.core.assert_that import assert_that
5 from hamcrest.core.core.isequal import equal_to
6 import unittest
7
8 __author__ = "Jon Reid"
9 __copyright__ = "Copyright 2011 hamcrest.org"
10 __license__ = "BSD, see License.txt"
11
12
13 class AssertThatTest(unittest.TestCase):
14
15 def testShouldBeSilentOnSuccessfulMatch(self):
16 assert_that(1, equal_to(1))
17
18 def testAssertionErrorShouldDescribeExpectedAndActual(self):
19 expected = 'EXPECTED'
20 actual = 'ACTUAL'
21
22 expectedMessage = "\nExpected: 'EXPECTED'\n but: was 'ACTUAL'\n"
23
24 try:
25 assert_that(actual, equal_to(expected))
26 except AssertionError, e:
27 self.assertEqual(expectedMessage, str(e))
28 return
29 self.fail('should have failed')
30
31 def testAssertionErrorShouldIncludeOptionalReason(self):
32 expected = 'EXPECTED'
33 actual = 'ACTUAL'
34
35 expectedMessage = "REASON\nExpected: 'EXPECTED'\n but: was 'ACTUAL'\n"
36
37 try:
38 assert_that(actual, equal_to(expected), 'REASON')
39 except AssertionError, e:
40 self.assertEqual(expectedMessage, str(e))
41 return
42 self.fail('should have failed')
43
44 def testCanTestBoolDirectly(self):
45 assert_that(True, 'should accept True')
46
47 try:
48 assert_that(False, 'FAILURE REASON')
49 except AssertionError, e:
50 self.assertEqual('FAILURE REASON', str(e))
51 return
52
53 self.fail('should have failed')
54
55 def testCanTestBoolDirectlyWithoutReason(self):
56 assert_that(True)
57
58 try:
59 assert_that(False)
60 except AssertionError, e:
61 self.assertEqual('Assertion failed', str(e))
62 return
63
64 self.fail('should have failed')
65
66
67 if __name__ == "__main__":
68 unittest.main()
+0
-28
hamcrest_unit_test/base_matcher_test.py less more
0 if __name__ == "__main__":
1 import sys
2 sys.path.insert(0, '..')
3
4 from hamcrest.core.base_matcher import *
5
6 import unittest
7
8 __author__ = "Jon Reid"
9 __copyright__ = "Copyright 2011 hamcrest.org"
10 __license__ = "BSD, see License.txt"
11
12
13 class TestingBaseMatcher(BaseMatcher):
14
15 def describe_to(self, description):
16 description.append_text('SOME DESCRIPTION')
17
18
19 class BaseMatcherTest(unittest.TestCase):
20
21 def testStrFunctionShouldDescribeMatcher(self):
22 matcher = TestingBaseMatcher()
23 self.assertEqual('SOME DESCRIPTION', str(matcher))
24
25
26 if __name__ == "__main__":
27 unittest.main()
+0
-0
hamcrest_unit_test/collection/__init__.py less more
(Empty file)
+0
-52
hamcrest_unit_test/collection/isdict_containing_test.py less more
0 if __name__ == '__main__':
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.library.collection.isdict_containing import *
6
7 from hamcrest.core.core.isequal import equal_to
8
9 from hamcrest_unit_test.matcher_test import MatcherTest
10 from quasidict import QuasiDictionary
11 import unittest
12
13 __author__ = "Jon Reid"
14 __copyright__ = "Copyright 2011 hamcrest.org"
15 __license__ = "BSD, see License.txt"
16
17
18 class IsDictContainingTest(MatcherTest):
19
20 def testMatchesDictionaryContainingMatchingKeyAndValue(self):
21 dict = {'a': 1, 'b': 2}
22 self.assert_matches('has a:1', has_entry(equal_to('a'), equal_to(1)), dict)
23 self.assert_matches('has b:2', has_entry(equal_to('b'), equal_to(2)), dict)
24 self.assert_does_not_match('no c:3', has_entry(equal_to('c'), equal_to(3)), dict)
25
26 def testProvidesConvenientShortcutForMatchingWithEqualTo(self):
27 dict = {'a': 1, 'b': 2}
28 self.assert_matches('has a:1', has_entry('a', equal_to(1)), dict)
29 self.assert_matches('has b:2', has_entry(equal_to('b'), 2), dict)
30 self.assert_does_not_match('no c:3', has_entry('c', 3), dict)
31
32 def testMatchesAnyConformingDictionary(self):
33 self.assert_matches('quasi-dictionary', has_entry(1, '1'), QuasiDictionary())
34 self.assert_does_not_match('non-dictionary', has_entry(1, '1'), object())
35
36 def testHasReadableDescription(self):
37 self.assert_description("a dictionary containing ['a': <1>]",
38 has_entry('a', 1))
39
40 def testSuccessfulMatchDoesNotGenerateMismatchDescription(self):
41 self.assert_no_mismatch_description(has_entry('a', 1), {'a': 1})
42
43 def testMismatchDescriptionShowsActualArgument(self):
44 self.assert_mismatch_description("was 'bad'", has_entry('a', 1), 'bad')
45
46 def testDescribeMismatch(self):
47 self.assert_describe_mismatch("was 'bad'", has_entry('a', 1), 'bad')
48
49
50 if __name__ == '__main__':
51 unittest.main()
+0
-125
hamcrest_unit_test/collection/isdict_containingentries_test.py less more
0 if __name__ == '__main__':
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.library.collection.isdict_containingentries import *
6
7 from hamcrest.core.core.isequal import equal_to
8 from hamcrest_unit_test.matcher_test import MatcherTest
9 import unittest
10
11 __author__ = "Jon Reid"
12 __copyright__ = "Copyright 2011 hamcrest.org"
13 __license__ = "BSD, see License.txt"
14
15
16 class IsDictContainingEntriesTest(MatcherTest):
17
18 def testMatcherCreationRequiresEvenNumberOfPositionalArgs(self):
19 self.assertRaises(ValueError, has_entries, 'a', 'b', 'c')
20
21 def testDoesNotMatchNonDictionary(self):
22 self.assert_does_not_match('non-dictionary',
23 has_entries('a', equal_to(1)), object())
24
25 def testMatchesDictLike(self):
26 class DictLike(object):
27 def __getitem__(self, key):
28 return 'value: ' + str(key)
29 def __contains__(self, key):
30 return True
31 self.assert_matches('matches a dictionary-like object',
32 has_entries('a', equal_to('value: a')),
33 DictLike())
34
35 def testMatchesUsingSingleDictionaryArgument(self):
36 target = {'a': 1, 'b': 2, 'c': 3}
37 self.assert_matches('has a & b',
38 has_entries({'a':equal_to(1), 'b':equal_to(2)}), target)
39 self.assert_matches('has c & a',
40 has_entries({'c':equal_to(3), 'a':equal_to(1)}), target)
41 self.assert_does_not_match('no d:3',
42 has_entries({'b':equal_to(2), 'd':equal_to(3)}), target)
43
44 def testMatcheSingleDictionaryArgumentWithImplicitEqualTo(self):
45 target = {'a': 1, 'b': 2, 'c': 3}
46 self.assert_matches('has a & b',
47 has_entries({'a':1, 'b':2}), target)
48 self.assert_matches('has c & a',
49 has_entries({'c':3, 'a':1}), target)
50 self.assert_does_not_match('no d:3',
51 has_entries({'b':2, 'd': 3}), target)
52
53 def testMatchesUsingKwargs(self):
54 target = {'a': 1, 'b': 2, 'c': 3}
55 self.assert_matches('has a & b',
56 has_entries(a=equal_to(1), b=equal_to(2)), target)
57 self.assert_matches('has c & a',
58 has_entries(c=equal_to(3), a=equal_to(1)), target)
59 self.assert_does_not_match('no d:3',
60 has_entries(b=equal_to(2), d=equal_to(3)), target)
61
62 def testMatchesKwargsWithImplicitEqualTo(self):
63 target = {'a': 1, 'b': 2, 'c': 3}
64 self.assert_matches('has a & b',
65 has_entries(a=1, b=2), target)
66 self.assert_matches('has c & a',
67 has_entries(c=3, a=1), target)
68 self.assert_does_not_match('no d:3',
69 has_entries(b=2, d=3), target)
70
71 def testMatchesDictionaryContainingSingleKeyWithMatchingValue(self):
72 target = {'a': 1, 'b': 2}
73 self.assert_matches('has a:1', has_entries('a', equal_to(1)), target)
74 self.assert_matches('has b:2', has_entries('b', equal_to(2)), target)
75 self.assert_does_not_match('no b:3', has_entries('b', equal_to(3)), target)
76 self.assert_does_not_match('no c:2', has_entries('c', equal_to(2)), target)
77
78 def testMatchesDictionaryContainingMultipleKeysWithMatchingValues(self):
79 target = {'a': 1, 'b': 2, 'c': 3}
80 self.assert_matches('has a & b',
81 has_entries('a', equal_to(1), 'b', equal_to(2)), target)
82 self.assert_matches('has c & a',
83 has_entries('c', equal_to(3), 'a', equal_to(1)), target)
84 self.assert_does_not_match('no d:3',
85 has_entries('b', equal_to(3), 'd', equal_to(3)), target)
86
87 def testProvidesConvenientShortcutForMatchingWithEqualTo(self):
88 target = {'a': 1, 'b': 2, 'c': 3}
89 self.assert_matches('has a & b', has_entries('a', 1, 'b', 2), target)
90 self.assert_matches('has c & a', has_entries('c', 3, 'a', 1), target)
91 self.assert_does_not_match('no d:4', has_entries('b', 3, 'd', 4), target)
92
93 def testHasReadableDescription(self):
94 self.assert_description("a dictionary containing {'a': <1>, 'b': <2>}",
95 has_entries('a', 1, 'b', 2))
96
97 def testSuccessfulMatchDoesNotGenerateMismatchDescription(self):
98 self.assert_no_mismatch_description(has_entries('a', 1), {'a': 1})
99
100 def testMismatchDescriptionOfNonDictionaryShowsActualArgument(self):
101 self.assert_mismatch_description("'bad' is not a mapping object", has_entries('a', 1), 'bad')
102
103 def testMismatchDescriptionOfDictionaryWithoutKey(self):
104 self.assert_mismatch_description("no 'b' key in <{'a': 1, 'c': 3}>",
105 has_entries('a', 1, 'b', 2), {'a': 1, 'c': 3})
106
107 def testMismatchDescriptionOfDictionaryWithNonMatchingValue(self):
108 self.assert_mismatch_description("value for 'a' was <2>",
109 has_entries('a', 1), {'a': 2})
110
111 def testDescribeMismatchOfNonDictionaryShowsActualArgument(self):
112 self.assert_describe_mismatch("'bad' is not a mapping object", has_entries('a', 1), 'bad')
113
114 def testDescribeMismatchOfDictionaryWithoutKey(self):
115 self.assert_describe_mismatch("no 'b' key in <{'a': 1, 'c': 3}>",
116 has_entries('a', 1, 'b', 2), {'a': 1, 'c': 3})
117
118 def testDescribeMismatchOfDictionaryWithNonMatchingValue(self):
119 self.assert_describe_mismatch("value for 'a' was <2>",
120 has_entries('a', 1), {'a': 2})
121
122
123 if __name__ == '__main__':
124 unittest.main()
+0
-58
hamcrest_unit_test/collection/isdict_containingkey_test.py less more
0 if __name__ == '__main__':
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.library.collection.isdict_containingkey import *
6
7 from hamcrest.core.core.isequal import equal_to
8 from hamcrest_unit_test.matcher_test import MatcherTest
9 from quasidict import QuasiDictionary
10 import unittest
11
12 __author__ = "Jon Reid"
13 __copyright__ = "Copyright 2011 hamcrest.org"
14 __license__ = "BSD, see License.txt"
15
16
17 class IsDictContainingKeyTest(MatcherTest):
18
19 def testMatchesSingletonDictionaryContainingKey(self):
20 dict = {'a': 1}
21 self.assert_matches('same single key', has_key(equal_to('a')), dict)
22
23 def testMatchesDictionaryContainingKey(self):
24 dict = {'a': 1, 'b': 2, 'c': 3}
25 self.assert_matches('Matches a', has_key(equal_to('a')), dict)
26 self.assert_matches('Matches c', has_key(equal_to('c')), dict)
27
28 def testProvidesConvenientShortcutForMatchingWithEqualTo(self):
29 dict = {'a': 1, 'b': 2, 'c': 3}
30 self.assert_matches('Matches c', has_key('c'), dict)
31
32 def testDoesNotMatchEmptyDictionary(self):
33 self.assert_does_not_match('empty', has_key('foo'), {});
34
35 def testDoesNotMatchDictionaryMissingKey(self):
36 dict = {'a': 1, 'b': 2, 'c': 3}
37 self.assert_does_not_match('no matching key', has_key('d'), dict)
38
39 def testMatchesAnyConformingDictionary(self):
40 self.assert_matches('quasi-dictionary', has_key(1), QuasiDictionary())
41 self.assert_does_not_match('non-dictionary', has_key(1), object())
42
43 def testHasReadableDescription(self):
44 self.assert_description("a dictionary containing key 'a'", has_key('a'))
45
46 def testSuccessfulMatchDoesNotGenerateMismatchDescription(self):
47 self.assert_no_mismatch_description(has_key('a'), {'a': 1})
48
49 def testMismatchDescriptionShowsActualArgument(self):
50 self.assert_mismatch_description("was 'bad'", has_key('a'), 'bad')
51
52 def testDescribeMismatch(self):
53 self.assert_describe_mismatch("was 'bad'", has_key('a'), 'bad')
54
55
56 if __name__ == '__main__':
57 unittest.main()
+0
-58
hamcrest_unit_test/collection/isdict_containingvalue_test.py less more
0 if __name__ == '__main__':
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.library.collection.isdict_containingvalue import *
6
7 from hamcrest.core.core.isequal import equal_to
8 from hamcrest_unit_test.matcher_test import MatcherTest
9 from quasidict import QuasiDictionary
10 import unittest
11
12 __author__ = "Jon Reid"
13 __copyright__ = "Copyright 2011 hamcrest.org"
14 __license__ = "BSD, see License.txt"
15
16
17 class IsDictContainingValueTest(MatcherTest):
18
19 def testMatchesSingletonDictionaryContainingValue(self):
20 dict = {'a': 1}
21 self.assert_matches('same single value', has_value(equal_to(1)), dict)
22
23 def testMatchesDictionaryContainingValue(self):
24 dict = {'a': 1, 'b': 2, 'c': 3}
25 self.assert_matches('Matches 1', has_value(equal_to(1)), dict)
26 self.assert_matches('Matches 3', has_value(equal_to(3)), dict)
27
28 def testProvidesConvenientShortcutForMatchingWithEqualTo(self):
29 dict = {'a': 1, 'b': 2, 'c': 3}
30 self.assert_matches('Matches 3', has_value(3), dict)
31
32 def testDoesNotMatchEmptyDictionary(self):
33 self.assert_does_not_match('empty', has_value(1), {});
34
35 def testDoesNotMatchDictionaryMissingValue(self):
36 dict = {'a': 1, 'b': 2, 'c': 3}
37 self.assert_does_not_match('no matching value', has_value(4), dict)
38
39 def testMatchesAnyConformingDictionary(self):
40 self.assert_matches('quasi-dictionary', has_value('1'), QuasiDictionary())
41 self.assert_does_not_match('non-dictionary', has_value('1'), object())
42
43 def testHasReadableDescription(self):
44 self.assert_description("a dictionary containing value 'a'", has_value('a'))
45
46 def testSuccessfulMatchDoesNotGenerateMismatchDescription(self):
47 self.assert_no_mismatch_description(has_value(1), {'a': 1})
48
49 def testMismatchDescriptionShowsActualArgument(self):
50 self.assert_mismatch_description("was 'bad'", has_value(1), 'bad')
51
52 def testDescribeMismatch(self):
53 self.assert_describe_mismatch("was 'bad'", has_value(1), 'bad')
54
55
56 if __name__ == '__main__':
57 unittest.main()
+0
-42
hamcrest_unit_test/collection/isin_test.py less more
0 if __name__ == '__main__':
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.library.collection.isin import *
6
7 from hamcrest_unit_test.matcher_test import MatcherTest
8 import unittest
9
10 __author__ = "Jon Reid"
11 __copyright__ = "Copyright 2011 hamcrest.org"
12 __license__ = "BSD, see License.txt"
13
14
15 sequence = ('a', 'b', 'c')
16
17 class IsInTest(MatcherTest):
18
19 def testReturnsTrueIfArgumentIsInSequence(self):
20 matcher = is_in(sequence)
21
22 self.assert_matches('has a', matcher, 'a')
23 self.assert_matches('has b', matcher, 'b')
24 self.assert_matches('has c', matcher, 'c')
25 self.assert_does_not_match('no d', matcher, 'd')
26
27 def testHasReadableDescription(self):
28 self.assert_description("one of ('a', 'b', 'c')", is_in(sequence))
29
30 def testSuccessfulMatchDoesNotGenerateMismatchDescription(self):
31 self.assert_no_mismatch_description(is_in(sequence), 'a')
32
33 def testMismatchDescriptionShowsActualArgument(self):
34 self.assert_mismatch_description("was 'bad'", is_in(sequence), 'bad')
35
36 def testDescribeMismatch(self):
37 self.assert_describe_mismatch("was 'bad'", is_in(sequence), 'bad')
38
39
40 if __name__ == '__main__':
41 unittest.main()
+0
-97
hamcrest_unit_test/collection/issequence_containing_test.py less more
0 if __name__ == '__main__':
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.library.collection.issequence_containing import *
6
7 from hamcrest.core.core.isequal import equal_to
8 from hamcrest_unit_test.matcher_test import MatcherTest
9 from quasisequence import QuasiSequence
10 import unittest
11
12 __author__ = "Jon Reid"
13 __copyright__ = "Copyright 2011 hamcrest.org"
14 __license__ = "BSD, see License.txt"
15
16
17 class IsSequenceContainingTest(MatcherTest):
18
19 def testMatchesASequenceThatContainsAnElementMatchingTheGivenMatcher(self):
20 self.assert_matches("sequence contains 'a'",
21 has_item(equal_to('a')), ['a', 'b', 'c'])
22
23 def testNoMatchIfSequenceDoesntContainAnElementMatchingTheGivenMatcher(self):
24 self.assert_does_not_match("sequence without 'a'",
25 has_item(equal_to('a')), ['b', 'c'])
26 self.assert_does_not_match('empty', has_item(equal_to('a')), [])
27
28 def testProvidesConvenientShortcutForMatchingWithEqualTo(self):
29 self.assert_matches("sequence contains 'a'",
30 has_item('a'), ['a', 'b', 'c'])
31 self.assert_does_not_match("sequence without 'a'",
32 has_item('a'), ['b', 'c'])
33
34 def testMatchesAnyConformingSequence(self):
35 self.assert_matches('quasi-sequence', has_item(1), QuasiSequence())
36 self.assert_does_not_match('non-sequence', has_item(1), object())
37
38 def testHasAReadableDescription(self):
39 self.assert_description("a sequence containing 'a'", has_item('a'))
40
41 def testSuccessfulMatchDoesNotGenerateMismatchDescription(self):
42 self.assert_no_mismatch_description(has_item('a'), ['a', 'b'])
43
44 def testMismatchDescriptionShowsActualArgument(self):
45 self.assert_mismatch_description("was <42>", has_item('a'), 42)
46
47 def testDescribeMismatch(self):
48 self.assert_describe_mismatch("was <42>", has_item('a'), 42)
49
50
51 class IsSequenceContainingItemsTest(MatcherTest):
52
53 def testShouldMatchCollectionContainingAllItems(self):
54 self.assert_matches('contains all items',
55 has_items(equal_to('a'), equal_to('b'), equal_to('c')),
56 ('a', 'b', 'c'))
57
58 def testProvidesConvenientShortcutForMatchingWithEqualTo(self):
59 self.assert_matches('Values automatically wrapped with equal_to',
60 has_items('a', 'b', 'c'),
61 ('a', 'b', 'c'))
62
63 def testShouldMatchCollectionContainingAllItemsInDifferentOrder(self):
64 self.assert_matches('all items in different order',
65 has_items('a', 'b', 'c'),
66 ('c', 'b', 'a'))
67
68 def testShouldMatchCollectionContainingAllItemsPlusExtras(self):
69 self.assert_matches('all items plus extras',
70 has_items('a', 'b', 'c'),
71 ('e', 'c', 'b', 'a', 'd'))
72
73 def testNoMatchIfCollectionDoesntSatisfyAllMatchers(self):
74 self.assert_does_not_match("missing 'a'",
75 has_items('a', 'b', 'c'),
76 ('e', 'c', 'b', 'd'))
77
78 def testHasAReadableDescription(self):
79 self.assert_description(
80 "(a sequence containing 'a' and a sequence containing 'b')",
81 has_items('a', 'b'))
82
83 def testSuccessfulMatchDoesNotGenerateMismatchDescription(self):
84 self.assert_no_mismatch_description(has_items('a', 'b'), ['a', 'b'])
85
86 def testMismatchDescriptionShowsFirstUnmetMatcherAndActualArgument(self):
87 self.assert_mismatch_description("a sequence containing 'a' was <42>",
88 has_items('a', 'b'), 42)
89
90 def testDescribeMismatch(self):
91 self.assert_describe_mismatch("a sequence containing 'a' was <42>",
92 has_items('a', 'b'), 42)
93
94
95 if __name__ == '__main__':
96 unittest.main()
+0
-76
hamcrest_unit_test/collection/issequence_containinginanyorder_test.py less more
0 if __name__ == '__main__':
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.library.collection.issequence_containinginanyorder import *
6
7 from hamcrest.core.core.isequal import equal_to
8 from hamcrest_unit_test.matcher_test import MatcherTest
9 from quasisequence import QuasiSequence
10 import unittest
11
12 __author__ = "Jon Reid"
13 __copyright__ = "Copyright 2011 hamcrest.org"
14 __license__ = "BSD, see License.txt"
15
16
17 class IsSequenceContainingInAnyOrderTest(MatcherTest):
18
19 def testMatchingSingleItemSequence(self):
20 self.assert_matches("Single item sequence",
21 contains_inanyorder(equal_to(1)), [1])
22
23 def testMatchesSequenceInOrder(self):
24 self.assert_matches("In order",
25 contains_inanyorder(equal_to(1), equal_to(2)), [1,2])
26
27 def testMatchesSequenceOutOfOrder(self):
28 self.assert_matches("Out of order",
29 contains_inanyorder(equal_to(1), equal_to(2)),
30 [2,1])
31
32 def testProvidesConvenientShortcutForMatchingWithEqualTo(self):
33 self.assert_matches("Values automatically wrapped with equal_to",
34 contains_inanyorder(1,2), [2,1])
35
36 def testDoesNotMatchEmptySequence(self):
37 self.assert_mismatch_description("no item matches: <1>, <2> in []",
38 contains_inanyorder(1, 2), [])
39
40 def testEmptySequenceMatchesEmptySequence(self):
41 self.assert_matches("Empty sequence", contains_inanyorder(), [])
42
43 def testDoesNotMatchIfOneOfMultipleItemsMismatch(self):
44 self.assert_mismatch_description("not matched: <4>",
45 contains_inanyorder(1,2,3), [1,2,4])
46
47 def testDoesNotMatchWithMoreElementsThanExpected(self):
48 self.assert_mismatch_description("not matched: <2>",
49 contains_inanyorder(1,3), [1,2,3])
50
51 def testDoesNotMatchWithFewerElementsThanExpected(self):
52 self.assert_mismatch_description(
53 "no item matches: <4> in [<1>, <2>, <3>]",
54 contains_inanyorder(1,2,3,4), [1,2,3])
55
56 def testMatchesAnyConformingSequence(self):
57 self.assert_matches('quasi-sequence', contains_inanyorder(1,2),
58 QuasiSequence())
59 self.assert_does_not_match('non-sequence', contains_inanyorder(1,2),
60 object())
61
62 def testHasAReadableDescription(self):
63 self.assert_description("a sequence over [<1>, <2>] in any order",
64 contains_inanyorder(1,2))
65
66 def testDescribeMismatch(self):
67 self.assert_describe_mismatch('not matched: <3>',
68 contains_inanyorder(1,2), [1,3])
69
70 def testDescribeMismatchOfNonSequence(self):
71 self.assert_describe_mismatch("was <3>", contains_inanyorder(1,2), 3)
72
73
74 if __name__ == '__main__':
75 unittest.main()
+0
-69
hamcrest_unit_test/collection/issequence_containinginorder_test.py less more
0 if __name__ == '__main__':
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.library.collection.issequence_containinginorder import *
6
7 from hamcrest.core.core.isequal import equal_to
8 from hamcrest_unit_test.matcher_test import MatcherTest
9 from quasisequence import QuasiSequence
10 import unittest
11
12 __author__ = "Jon Reid"
13 __copyright__ = "Copyright 2011 hamcrest.org"
14 __license__ = "BSD, see License.txt"
15
16
17 class IsSequenceContainingInOrderTest(MatcherTest):
18
19 def testMatchingSingleItemSequence(self):
20 self.assert_matches("Single item sequence", contains(equal_to(1)), [1])
21
22 def testMatchingMultipleItemSequence(self):
23 self.assert_matches("Multiple item sequence",
24 contains(equal_to(1), equal_to(2), equal_to(3)),
25 [1,2,3])
26
27 def testProvidesConvenientShortcutForMatchingWithEqualTo(self):
28 self.assert_matches("Values automatically wrapped with equal_to",
29 contains(1, 2, 3),
30 [1,2,3])
31
32 def testDoesNotMatchWithMoreElementsThanExpected(self):
33 self.assert_mismatch_description("Not matched: <4>",
34 contains(1,2,3), [1,2,3,4])
35
36 def testDoesNotMatchWithFewerElementsThanExpected(self):
37 self.assert_mismatch_description("No item matched: <3>",
38 contains(1,2,3), [1,2])
39
40 def testDoesNotMatchIfSingleItemMismatches(self):
41 self.assert_mismatch_description("item 0: was <3>", contains(4), [3])
42
43 def testDoesNotMatchIfOneOfMultipleItemsMismatch(self):
44 self.assert_mismatch_description("item 2: was <4>",
45 contains(1,2,3), [1,2,4])
46
47 def testDoesNotMatchEmptySequence(self):
48 self.assert_mismatch_description("No item matched: <4>",
49 contains(4), [])
50
51 def testEmptySequenceMatchesEmptySequence(self):
52 self.assert_matches("Empty sequence", contains(), [])
53
54 def testMatchesAnyConformingSequence(self):
55 self.assert_matches('quasi-sequence', contains(1,2), QuasiSequence())
56 self.assert_does_not_match('non-sequence', contains(1,2), object())
57
58 def testHasAReadableDescription(self):
59 self.assert_description("a sequence containing [<1>, <2>]", contains(1,2))
60
61 def testDescribeMismatch(self):
62 self.assert_describe_mismatch('item 1: was <3>', contains(1,2), [1,3])
63
64 def testDescribeMismatchOfNonSequence(self):
65 self.assert_describe_mismatch("was <3>", contains(1,2), 3)
66
67 if __name__ == '__main__':
68 unittest.main()
+0
-66
hamcrest_unit_test/collection/issequence_onlycontaining_test.py less more
0 if __name__ == '__main__':
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.library.collection.issequence_onlycontaining import *
6
7 from hamcrest.core.core.isequal import equal_to
8 from hamcrest.library.number.ordering_comparison import less_than
9 from hamcrest_unit_test.matcher_test import MatcherTest
10 from quasisequence import QuasiSequence
11 import unittest
12
13 __author__ = "Jon Reid"
14 __copyright__ = "Copyright 2011 hamcrest.org"
15 __license__ = "BSD, see License.txt"
16
17
18 class IsSequenceOnlyContainingTest(MatcherTest):
19
20 def testMatchesSingletonList(self):
21 self.assert_matches('singleton list', only_contains(equal_to(1)), [1])
22
23 def testMatchesAllItemsWithOneMatcher(self):
24 self.assert_matches('one matcher',
25 only_contains(less_than(3)), [0, 1, 2])
26
27 def testMatchesAllItemsWithMultipleMatchers(self):
28 self.assert_matches('multiple matchers',
29 only_contains(less_than(3), equal_to(7)),
30 [0, 7, 1, 2])
31
32 def testProvidesConvenientShortcutForMatchingWithEqualTo(self):
33 self.assert_matches('Values automatically wrapped with equal_to',
34 only_contains(less_than(3), 7),
35 [0, 7, 1, 2])
36
37 def testDoesNotMatchListWithMismatchingItem(self):
38 self.assert_does_not_match('3 is not less than 3',
39 only_contains(less_than(3)), [1, 2, 3])
40
41 def testDoesNotMatchEmptyList(self):
42 self.assert_does_not_match('empty', only_contains('foo'), [])
43
44 def testMatchesAnyConformingSequence(self):
45 class ObjectWithLenOnly:
46 def __len__(self): return 20
47 self.assert_matches('quasi-sequence',
48 only_contains(less_than(3)), QuasiSequence())
49 self.assert_does_not_match('non-sequence', only_contains(1), object())
50 self.assert_does_not_match('non-sequence with length',
51 only_contains(1), ObjectWithLenOnly())
52
53 def testHasAReadableDescription(self):
54 self.assert_description('a sequence containing items matching (<1> or <2>)',
55 only_contains(1,2))
56
57 def testDescribeMismatch(self):
58 self.assert_describe_mismatch("was 'bad'", only_contains(1,2), 'bad')
59
60 def testDescribeMismatchOfNonSequence(self):
61 self.assert_describe_mismatch("was <3>", only_contains(1,2), 3)
62
63
64 if __name__ == '__main__':
65 unittest.main()
+0
-44
hamcrest_unit_test/collection/quasidict.py less more
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4
5 class QuasiDictionary:
6 def items(self):
7 return QuasiDictionaryItemIterator()
8
9 def keys(self):
10 return QuasiDictionaryKeyIterator()
11
12 def values(self):
13 return QuasiDictionaryValueIterator()
14
15
16 class BaseQuasiDictionaryIterator:
17 def __init__(self):
18 self.index = 1
19
20 def __iter__(self):
21 return self
22
23 def next(self):
24 if self.index >= 3:
25 raise StopIteration
26 result = self.indexToResult()
27 self.index += 1
28 return result
29
30
31 class QuasiDictionaryItemIterator(BaseQuasiDictionaryIterator):
32 def indexToResult(self):
33 return (self.index, str(self.index))
34
35
36 class QuasiDictionaryKeyIterator(BaseQuasiDictionaryIterator):
37 def indexToResult(self):
38 return self.index
39
40
41 class QuasiDictionaryValueIterator(BaseQuasiDictionaryIterator):
42 def indexToResult(self):
43 return str(self.index)
+0
-26
hamcrest_unit_test/collection/quasisequence.py less more
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4
5 class QuasiSequence:
6 def __iter__(self):
7 return QuasiSequenceIterator()
8
9 def __len__(self):
10 return 2
11
12
13 class QuasiSequenceIterator:
14 def __init__(self):
15 self.index = 1
16
17 def __iter__(self):
18 return self
19
20 def next(self):
21 if self.index >= 3:
22 raise StopIteration
23 result = self.index
24 self.index += 1
25 return result
+0
-0
hamcrest_unit_test/core/__init__.py less more
(Empty file)
+0
-82
hamcrest_unit_test/core/allof_test.py less more
0 if __name__ == '__main__':
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.core.core.allof import *
6
7 from hamcrest.core.core.isequal import equal_to
8 from hamcrest_unit_test.matcher_test import MatcherTest
9 import unittest
10
11 __author__ = "Jon Reid"
12 __copyright__ = "Copyright 2011 hamcrest.org"
13 __license__ = "BSD, see License.txt"
14
15
16 class AllOfTest(MatcherTest):
17
18 def testMatchesIfArgumentSatisfiesBothOfTwoOtherMatchers(self):
19 self.assert_matches('both matchers',
20 all_of(equal_to('good'), equal_to('good')),
21 'good')
22
23 def testProvidesConvenientShortcutForMatchingWithEqualTo(self):
24 self.assert_matches('both matchers',
25 all_of('good', 'good'),
26 'good')
27
28 def testNoMatchIfArgumentFailsToSatisfyEitherOfTwoOtherMatchers(self):
29 self.assert_does_not_match('first matcher',
30 all_of(equal_to('bad'), equal_to('good')),
31 'good')
32 self.assert_does_not_match('second matcher',
33 all_of(equal_to('good'), equal_to('bad')),
34 'good')
35 self.assert_does_not_match('either matcher',
36 all_of(equal_to('bad'), equal_to('bad')),
37 'good')
38
39 def testMatchesIfArgumentSatisfiesAllOfManyOtherMatchers(self):
40 self.assert_matches('all matchers',
41 all_of(equal_to('good'),
42 equal_to('good'),
43 equal_to('good'),
44 equal_to('good'),
45 equal_to('good')),
46 'good')
47
48 def testNoMatchIfArgumentFailsToSatisfyAllOfManyOtherMatchers(self):
49 self.assert_does_not_match('matcher in the middle',
50 all_of(equal_to('good'),
51 equal_to('good'),
52 equal_to('good'),
53 equal_to('bad'),
54 equal_to('good'),
55 equal_to('good')),
56 'good')
57
58 def testHasAReadableDescription(self):
59 self.assert_description("('good' and 'bad' and 'ugly')",
60 all_of(equal_to('good'), equal_to('bad'), equal_to('ugly')))
61
62 def testSuccessfulMatchDoesNotGenerateMismatchDescription(self):
63 self.assert_no_mismatch_description(
64 all_of(equal_to('good'), equal_to('good')),
65 'good')
66
67 def testMismatchDescriptionDescribesFirstFailingMatch(self):
68 self.assert_mismatch_description(
69 "'good' was 'bad'",
70 all_of(equal_to('bad'), equal_to('good')),
71 'bad')
72
73 def testDescribeMismatch(self):
74 self.assert_describe_mismatch(
75 "'good' was 'bad'",
76 all_of(equal_to('bad'), equal_to('good')),
77 'bad')
78
79
80 if __name__ == '__main__':
81 unittest.main()
+0
-87
hamcrest_unit_test/core/anyof_test.py less more
0 if __name__ == '__main__':
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.core.core.anyof import *
6
7 from hamcrest.core.core.isequal import equal_to
8 from hamcrest_unit_test.matcher_test import MatcherTest
9 import unittest
10
11 __author__ = "Jon Reid"
12 __copyright__ = "Copyright 2011 hamcrest.org"
13 __license__ = "BSD, see License.txt"
14
15
16 class AnyOfTest(MatcherTest):
17
18 def testMatchesIfArgumentSatisfiesEitherOrBothOfTwoOtherMatchers(self):
19 self.assert_matches('first matcher',
20 any_of(equal_to('good'), equal_to('bad')),
21 'good')
22 self.assert_matches('second matcher',
23 any_of(equal_to('bad'), equal_to('good')),
24 'good')
25 self.assert_matches('both matchers',
26 any_of(equal_to('good'), equal_to('good')),
27 'good')
28
29 def testProvidesConvenientShortcutForMatchingWithEqualTo(self):
30 self.assert_matches('first matcher',
31 any_of('good', 'bad'),
32 'good')
33 self.assert_matches('second matcher',
34 any_of('bad', 'good'),
35 'good')
36 self.assert_matches('both matchers',
37 any_of('good', 'good'),
38 'good')
39
40 def testNoMatchIfArgumentFailsToSatisfyEitherOfTwoOtherMatchers(self):
41 self.assert_does_not_match('either matcher',
42 any_of(equal_to('bad'), equal_to('bad')),
43 'good')
44
45 def testMatchesIfArgumentSatisfiesAnyOfManyOtherMatchers(self):
46 self.assert_matches('matcher in the middle',
47 any_of(equal_to('bad'),
48 equal_to('bad'),
49 equal_to('good'),
50 equal_to('bad'),
51 equal_to('bad')),
52 'good')
53
54 def testNoMatchIfArgumentFailsToSatisfyAnyOfManyOtherMatchers(self):
55 self.assert_does_not_match('all matchers',
56 any_of(equal_to('bad'),
57 equal_to('bad'),
58 equal_to('bad'),
59 equal_to('bad'),
60 equal_to('bad')),
61 'good')
62
63 def testHasAReadableDescription(self):
64 self.assert_description("('good' or 'bad' or 'ugly')",
65 any_of(equal_to('good'), equal_to('bad'), equal_to('ugly')))
66
67 def testSuccessfulMatchDoesNotGenerateMismatchDescription(self):
68 self.assert_no_mismatch_description(
69 any_of(equal_to('good'), equal_to('bad')),
70 'good')
71
72 def testMismatchDescriptionDescribesFirstFailingMatch(self):
73 self.assert_mismatch_description(
74 "was 'ugly'",
75 any_of(equal_to('bad'), equal_to('good')),
76 'ugly')
77
78 def testDescribeMismatch(self):
79 self.assert_describe_mismatch(
80 "was 'ugly'",
81 any_of(equal_to('bad'), equal_to('good')),
82 'ugly')
83
84
85 if __name__ == '__main__':
86 unittest.main()
+0
-58
hamcrest_unit_test/core/described_as_test.py less more
0 if __name__ == '__main__':
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.core.core.described_as import *
6
7 from hamcrest.core.core.isanything import anything
8 from hamcrest_unit_test.matcher_test import MatcherTest
9 from nevermatch import NeverMatch
10 import unittest
11
12 __author__ = "Jon Reid"
13 __copyright__ = "Copyright 2011 hamcrest.org"
14 __license__ = "BSD, see License.txt"
15
16
17 class DescribedAsTest(MatcherTest):
18
19 def testOverridesDescriptionOfNestedMatcherWithConstructorArgument(self):
20 m1 = described_as('m1 description', anything())
21 m2 = described_as('m2 description', NeverMatch())
22
23 self.assert_description('m1 description', m1)
24 self.assert_description('m2 description', m2)
25
26 def testAppendsValuesToDescription(self):
27 m = described_as('value 1 = %0, value 2 = %1', anything(), 33, 97)
28
29 self.assert_description('value 1 = <33>, value 2 = <97>', m)
30
31 def testDelegatesMatchingToNestedMatcher(self):
32 m1 = described_as('irrelevant', anything())
33 m2 = described_as('irrelevant', NeverMatch())
34
35 self.assertTrue(m1.matches(object()))
36 self.assertTrue(not m2.matches('hi'))
37
38 def testSuccessfulMatchDoesNotGenerateMismatchDescription(self):
39 self.assert_no_mismatch_description(
40 described_as('irrelevant', anything()),
41 object())
42
43 def testDelegatesMismatchDescriptionToNestedMatcher(self):
44 self.assert_mismatch_description(
45 NeverMatch.mismatch_description,
46 described_as('irrelevant', NeverMatch()),
47 'hi')
48
49 def testDelegatesDescribeMismatchToNestedMatcher(self):
50 self.assert_describe_mismatch(
51 NeverMatch.mismatch_description,
52 described_as('irrelevant', NeverMatch()),
53 'hi')
54
55
56 if __name__ == '__main__':
57 unittest.main()
+0
-57
hamcrest_unit_test/core/is_test.py less more
0 if __name__ == '__main__':
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.core.core.is_ import *
6
7 from hamcrest.core.core.isequal import equal_to
8 from hamcrest_unit_test.matcher_test import MatcherTest
9 from nevermatch import NeverMatch
10 import unittest
11
12 __author__ = "Jon Reid"
13 __copyright__ = "Copyright 2011 hamcrest.org"
14 __license__ = "BSD, see License.txt"
15
16
17 class IsTest(MatcherTest):
18
19 def testDelegatesMatchingToNestedMatcher(self):
20 self.assert_matches('should match', is_(equal_to(True)), True)
21 self.assert_matches('should match', is_(equal_to(False)), False)
22 self.assert_does_not_match('should not match', is_(equal_to(True)), False)
23 self.assert_does_not_match('should not match', is_(equal_to(False)), True)
24
25 def testDescriptionShouldPassThrough(self):
26 self.assert_description('<True>', is_(equal_to(True)))
27
28 def testProvidesConvenientShortcutForIsEqualTo(self):
29 self.assert_matches('should match', is_('A'), 'A');
30 self.assert_matches('should match', is_('B'), 'B');
31 self.assert_does_not_match('should not match', is_('A'), 'B');
32 self.assert_does_not_match('should not match', is_('B'), 'A');
33 self.assert_description("'A'", is_('A'));
34
35 def testProvidesConvenientShortcutForIsInstanceOf(self):
36 self.assert_matches('should match', is_(str), 'A');
37 self.assert_does_not_match('should not match', is_(int), 'A');
38
39 def testSuccessfulMatchDoesNotGenerateMismatchDescription(self):
40 self.assert_no_mismatch_description(is_('A'), 'A')
41
42 def testDelegatesMismatchDescriptionToNestedMatcher(self):
43 self.assert_mismatch_description(
44 NeverMatch.mismatch_description,
45 is_(NeverMatch()),
46 'hi')
47
48 def testDelegatesDescribeMismatchToNestedMatcher(self):
49 self.assert_describe_mismatch(
50 NeverMatch.mismatch_description,
51 is_(NeverMatch()),
52 'hi')
53
54
55 if __name__ == '__main__':
56 unittest.main()
+0
-35
hamcrest_unit_test/core/isanything_test.py less more
0 if __name__ == "__main__":
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.core.core.isanything import *
6
7 from hamcrest_unit_test.matcher_test import MatcherTest
8 import unittest
9
10 __author__ = "Jon Reid"
11 __copyright__ = "Copyright 2011 hamcrest.org"
12 __license__ = "BSD, see License.txt"
13
14
15 class IsAnythingTest(MatcherTest):
16
17 def testAlwaysEvaluatesToTrue(self):
18 self.assert_matches('None', anything(), None)
19 self.assert_matches('object', anything(), object())
20 self.assert_matches('string', anything(), 'hi')
21
22 def testHasUsefulDefaultDescription(self):
23 self.assert_description('ANYTHING', anything())
24
25 def testCanOverrideDescription(self):
26 description = 'DESCRIPTION'
27 self.assert_description(description, anything(description))
28
29 def testMatchAlwaysSucceedsSoShouldNotGenerateMismatchDescription(self):
30 self.assert_no_mismatch_description(anything(), 'hi')
31
32
33 if __name__ == "__main__":
34 unittest.main()
+0
-57
hamcrest_unit_test/core/isequal_test.py less more
0 if __name__ == '__main__':
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.core.core.isequal import *
6
7 from hamcrest_unit_test.matcher_test import MatcherTest
8 import unittest
9
10 __author__ = "Jon Reid"
11 __copyright__ = "Copyright 2011 hamcrest.org"
12 __license__ = "BSD, see License.txt"
13
14
15 class IsEqualTest(MatcherTest):
16
17 def testComparesObjectsUsingEquality(self):
18 self.assert_matches('equal numbers', equal_to(1), 1)
19 self.assert_does_not_match('unequal numbers', equal_to(1), 2)
20
21 def testCanCompareNoneValues(self):
22 self.assert_matches('None equals None', equal_to(None), None)
23
24 self.assert_does_not_match('None as argument', equal_to('hi'), None)
25 self.assert_does_not_match('None in equal_to', equal_to(None), 'hi')
26
27 def testHonorsArgumentEqImplementationEvenWithNone(self):
28 class AlwaysEqual:
29 def __eq__(self, obj): return True
30 class NeverEqual:
31 def __eq__(self, obj): return False
32 self.assert_matches("always equal", equal_to(None), AlwaysEqual())
33 self.assert_does_not_match("never equal", equal_to(None), NeverEqual())
34
35 def testIncludesTheResultOfCallingToStringOnItsArgumentInTheDescription(self):
36 argument_description = 'ARGUMENT DESCRIPTION'
37 class Argument:
38 def __str__(self): return argument_description
39 self.assert_description('<ARGUMENT DESCRIPTION>', equal_to(Argument()))
40
41 def testReturnsAnObviousDescriptionIfCreatedWithANestedMatcherByMistake(self):
42 inner_matcher = equal_to('NestedMatcher')
43 self.assert_description("<'NestedMatcher'>", equal_to(inner_matcher))
44
45 def testSuccessfulMatchDoesNotGenerateMismatchDescription(self):
46 self.assert_no_mismatch_description(equal_to('hi'), 'hi')
47
48 def testMismatchDescriptionShowsActualArgument(self):
49 self.assert_mismatch_description("was 'bad'", equal_to('good'), 'bad')
50
51 def testDescribeMismatch(self):
52 self.assert_describe_mismatch("was 'bad'", equal_to('good'), 'bad')
53
54
55 if __name__ == '__main__':
56 unittest.main()
+0
-41
hamcrest_unit_test/core/isinstanceof_test.py less more
0 if __name__ == '__main__':
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.core.core.isinstanceof import *
6
7 from hamcrest_unit_test.matcher_test import MatcherTest
8 import unittest
9
10 __author__ = "Jon Reid"
11 __copyright__ = "Copyright 2011 hamcrest.org"
12 __license__ = "BSD, see License.txt"
13
14
15 class IsInstanceOfTest(MatcherTest):
16
17 def testEvaluatesToTrueIfArgumentIsInstanceOfASpecificClass(self):
18 self.assert_matches('same class', instance_of(int), 1)
19
20 self.assert_does_not_match('different class', instance_of(int), 'hi')
21 self.assert_does_not_match('None', instance_of(int), None)
22
23 def testMatcherCreationRequiresType(self):
24 self.assertRaises(TypeError, instance_of, 'not a type')
25
26 def testHasAReadableDescription(self):
27 self.assert_description('an instance of int', instance_of(int));
28
29 def testSuccessfulMatchDoesNotGenerateMismatchDescription(self):
30 self.assert_no_mismatch_description(instance_of(int), 3)
31
32 def testMismatchDescriptionShowsActualArgument(self):
33 self.assert_mismatch_description("was 'bad'", instance_of(int), 'bad')
34
35 def testDescribeMismatch(self):
36 self.assert_describe_mismatch("was 'bad'", instance_of(int), 'bad')
37
38
39 if __name__ == '__main__':
40 unittest.main()
+0
-59
hamcrest_unit_test/core/isnone_test.py less more
0 if __name__ == '__main__':
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.core.core.isnone import *
6
7 from hamcrest_unit_test.matcher_test import MatcherTest
8 import unittest
9
10 __author__ = "Jon Reid"
11 __copyright__ = "Copyright 2011 hamcrest.org"
12 __license__ = "BSD, see License.txt"
13
14
15 class IsNoneTest(MatcherTest):
16
17 def testEvaluatesToTrueIfArgumentIsNone(self):
18 self.assert_matches('None', none(), None)
19
20 def testEvaluatesToFalseIfArgumentIsNotNone(self):
21 self.assert_does_not_match('not None', none(), object())
22
23 def testHasAReadableDescription(self):
24 self.assert_description('None', none());
25
26 def testSuccessfulMatchDoesNotGenerateMismatchDescription(self):
27 self.assert_no_mismatch_description(none(), None)
28
29 def testMismatchDescriptionShowsActualArgument(self):
30 self.assert_mismatch_description("was 'bad'", none(), 'bad')
31
32 def testDescribeMismatch(self):
33 self.assert_describe_mismatch("was 'bad'", none(), 'bad')
34
35
36 class NotNoneTest(MatcherTest):
37
38 def testEvaluatesToTrueIfArgumentIsNotNone(self):
39 self.assert_matches('not None', not_none(), object())
40
41 def testEvaluatesToFalseIfArgumentIsNone(self):
42 self.assert_does_not_match('None', not_none(), None)
43
44 def testHasAReadableDescription(self):
45 self.assert_description('not None', not_none());
46
47 def testSuccessfulMatchDoesNotGenerateMismatchDescription(self):
48 self.assert_no_mismatch_description(not_none(), 'hi')
49
50 def testMismatchDescriptionShowsActualArgument(self):
51 self.assert_mismatch_description("was <None>", not_none(), None)
52
53 def testDescribeMismatch(self):
54 self.assert_describe_mismatch("was <None>", not_none(), None)
55
56
57 if __name__ == '__main__':
58 unittest.main()
+0
-41
hamcrest_unit_test/core/isnot_test.py less more
0 if __name__ == '__main__':
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.core.core.isnot import *
6
7 from hamcrest.core.core.isequal import equal_to
8 from hamcrest_unit_test.matcher_test import MatcherTest
9 import unittest
10
11 __author__ = "Jon Reid"
12 __copyright__ = "Copyright 2011 hamcrest.org"
13 __license__ = "BSD, see License.txt"
14
15
16 class IsNotTest(MatcherTest):
17
18 def testEvaluatesToTheTheLogicalNegationOfAnotherMatcher(self):
19 self.assert_matches('invert mismatch', is_not(equal_to('A')), 'B')
20 self.assert_does_not_match('invert match', is_not(equal_to('A')), 'A')
21
22 def testProvidesConvenientShortcutForNotEqualTo(self):
23 self.assert_matches('invert mismatch', is_not('A'), 'B');
24 self.assert_does_not_match('invert match', is_not('A'), 'A');
25
26 def testHasAReadableDescription(self):
27 self.assert_description("not 'A'", is_not('A'));
28
29 def testSuccessfulMatchDoesNotGenerateMismatchDescription(self):
30 self.assert_no_mismatch_description(is_not('A'), 'B')
31
32 def testMismatchDescriptionShowsActualArgument(self):
33 self.assert_mismatch_description("was 'A'", is_not('A'), 'A')
34
35 def testDescribeMismatch(self):
36 self.assert_describe_mismatch("was 'A'", is_not('A'), 'A')
37
38
39 if __name__ == '__main__':
40 unittest.main()
+0
-64
hamcrest_unit_test/core/issame_test.py less more
0 if __name__ == '__main__':
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.core.core.issame import *
6
7 from hamcrest.core.string_description import StringDescription
8 from hamcrest_unit_test.matcher_test import MatcherTest
9 import re
10 import unittest
11
12 __author__ = "Jon Reid"
13 __copyright__ = "Copyright 2011 hamcrest.org"
14 __license__ = "BSD, see License.txt"
15
16
17 class IsSameTest(MatcherTest):
18
19 def testEvaluatesToTrueIfArgumentIsReferenceToASpecifiedObject(self):
20 o1 = object()
21 o2 = object()
22
23 self.assert_matches('same', same_instance(o1), o1)
24 self.assert_does_not_match('different', same_instance(o1), o2)
25
26 def testDescriptionIncludesMemoryAddress(self):
27 description = StringDescription()
28 expected = re.compile("same instance as 0x[0-9a-fA-F]+ 'abc'")
29
30 description.append_description_of(same_instance('abc'));
31 self.assertTrue(expected.match(str(description)))
32
33 def testSuccessfulMatchDoesNotGenerateMismatchDescription(self):
34 o1 = object()
35 self.assert_no_mismatch_description(same_instance(o1), o1)
36
37 def testMismatchDescriptionShowsActualArgumentAddress(self):
38 matcher = same_instance('foo')
39 description = StringDescription()
40 expected = re.compile("was 0x[0-9a-fA-F]+ 'hi'")
41
42 result = matcher.matches('hi', description)
43 self.assertFalse(result, 'Precondition: Matcher should not match item')
44 self.assertTrue(expected.match(str(description)))
45
46 def testMismatchDescriptionWithNilShouldNotIncludeAddress(self):
47 self.assert_mismatch_description("was <None>", same_instance('foo'), None)
48
49 def testDescribeMismatch(self):
50 matcher = same_instance('foo')
51 description = StringDescription()
52 expected = re.compile("was 0x[0-9a-fA-F]+ 'hi'")
53
54 matcher.describe_mismatch('hi', description)
55 expected = re.compile("was 0x[0-9a-fA-F]+ 'hi'")
56 self.assertTrue(expected.match(str(description)))
57
58 def testDescribeMismatchWithNilShouldNotIncludeAddress(self):
59 self.assert_describe_mismatch("was <None>", same_instance('foo'), None)
60
61
62 if __name__ == '__main__':
63 unittest.main()
+0
-18
hamcrest_unit_test/core/nevermatch.py less more
0 from hamcrest.core.base_matcher import BaseMatcher
1
2 __author__ = "Jon Reid"
3 __copyright__ = "Copyright 2011 hamcrest.org"
4 __license__ = "BSD, see License.txt"
5
6
7 class NeverMatch(BaseMatcher):
8
9 mismatch_description = 'NEVERMATCH'
10
11 def matches(self, item, mismatch_description=None):
12 if mismatch_description:
13 self.describe_mismatch(item, mismatch_description)
14 return False
15
16 def describe_mismatch(self, item, mismatch_description):
17 mismatch_description.append_text(NeverMatch.mismatch_description)
+0
-0
hamcrest_unit_test/integration/__init__.py less more
(Empty file)
+0
-40
hamcrest_unit_test/integration/match_equality_test.py less more
0 if __name__ == "__main__":
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.library.integration.match_equality import *
6
7 from hamcrest.core.core.isequal import equal_to
8 from hamcrest.core.string_description import tostring
9 import unittest
10
11 __author__ = "Chris Rose"
12 __copyright__ = "Copyright 2011 hamcrest.org"
13 __license__ = "BSD, see License.txt"
14
15
16 class MatchEqualityWrapperTest(unittest.TestCase):
17
18 def testMatcherIsEqualWhenMatchesIsTrue(self):
19 matcher = equal_to('bar')
20 assert match_equality(matcher) == 'bar'
21
22 def testMatcherIsNotEqualWhenMatchesIsFalse(self):
23 matcher = equal_to('bar')
24 assert match_equality(matcher) != 'foo'
25
26 def testMatcherStringIsMatcherDescription(self):
27 matcher = equal_to('bar')
28 assert str(match_equality(matcher)) == tostring(matcher)
29
30 def testMatcherReprIsMatcher(self):
31 matcher = equal_to('bar')
32 assert repr(match_equality(matcher)) == tostring(matcher)
33
34 def testMatchesWhenProvidedAnObject(self):
35 assert match_equality('bar') == 'bar'
36
37
38 if __name__ == "__main__":
39 unittest.main()
+0
-48
hamcrest_unit_test/matcher_test.py less more
0 from hamcrest.core.string_description import StringDescription
1
2 import unittest
3 import logging
4
5 log = logging.getLogger(__name__)
6
7 __author__ = "Jon Reid"
8 __copyright__ = "Copyright 2011 hamcrest.org"
9 __license__ = "BSD, see License.txt"
10
11
12 class MatcherTest(unittest.TestCase):
13
14 def assert_matches(self, message, matcher, arg):
15 try:
16 self.assertTrue(matcher.matches(arg), message)
17 except AssertionError:
18 description = StringDescription()
19 matcher.describe_mismatch(arg, description)
20 log.error(str(description))
21 raise
22
23 def assert_does_not_match(self, message, matcher, arg):
24 self.assertFalse(matcher.matches(arg), message)
25
26 def assert_description(self, expected, matcher):
27 description = StringDescription()
28 description.append_description_of(matcher);
29 self.assertEqual(expected, str(description))
30
31 def assert_no_mismatch_description(self, matcher, arg):
32 description = StringDescription()
33 result = matcher.matches(arg, description)
34 self.assertTrue(result, 'Precondition: Matcher should match item')
35 self.assertEqual('', str(description),
36 'Expected no mismatch description')
37
38 def assert_mismatch_description(self, expected, matcher, arg):
39 description = StringDescription()
40 result = matcher.matches(arg, description)
41 self.assertFalse(result, 'Precondition: Matcher should not match item')
42 self.assertEqual(expected, str(description))
43
44 def assert_describe_mismatch(self, expected, matcher, arg):
45 description = StringDescription()
46 matcher.describe_mismatch(arg, description)
47 self.assertEqual(expected, str(description))
+0
-0
hamcrest_unit_test/number/__init__.py less more
(Empty file)
+0
-62
hamcrest_unit_test/number/iscloseto_test.py less more
0 if __name__ == '__main__':
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.library.number.iscloseto import *
6
7 from hamcrest_unit_test.matcher_test import MatcherTest
8 import unittest
9
10 __author__ = "Jon Reid"
11 __copyright__ = "Copyright 2011 hamcrest.org"
12 __license__ = "BSD, see License.txt"
13
14
15 class IsCloseToTest(MatcherTest):
16
17 def testEvaluatesToTrueIfArgumentIsEqualToAValueWithinSomeError(self):
18 matcher = close_to(1.0, 0.5)
19
20 self.assert_matches('equal', matcher, 1.0)
21 self.assert_matches('less but within delta', matcher, 0.5)
22 self.assert_matches('greater but within delta', matcher, 1.5)
23
24 self.assert_does_not_match('too small', matcher, 0.4)
25 self.assert_does_not_match('too large', matcher, 1.6)
26
27 def testMatcherCreationAcceptsOtherNumericTypes(self):
28 close_to(5, 1)
29 close_to(5L, 1L)
30
31 def testMatcherCreationRequiresNumbers(self):
32 self.assertRaises(TypeError, close_to, 'a', 0.5)
33 self.assertRaises(TypeError, close_to, 1.0, 'a')
34
35 def testFailsIfMatchingAgainstNonNumber(self):
36 self.assert_does_not_match('not a number', close_to(1.0, 0.5), 'a')
37
38 def testHasAReadableDescription(self):
39 self.assert_description('a numeric value within <0.5> of <1.0>',
40 close_to(1.0, 0.5))
41
42 def testSuccessfulMatchDoesNotGenerateMismatchDescription(self):
43 self.assert_no_mismatch_description(close_to(1.0, 0.5), 1.0)
44
45 def testMismatchDescriptionShowsActualDeltaIfArgumentIsNumeric(self):
46 self.assert_mismatch_description('<1.7> differed by <0.7>',
47 close_to(1.0, 0.5), 1.7)
48
49 def testMismatchDescriptionShowsActualArgumentIfNotNumeric(self):
50 self.assert_mismatch_description("was 'bad'", close_to(1.0, 0.5), 'bad')
51
52 def testDescribeMismatchShowsActualDeltaIfArgumentIsNumeric(self):
53 self.assert_describe_mismatch('<1.7> differed by <0.7>',
54 close_to(1.0, 0.5), 1.7)
55
56 def testDescribeMismatchShowsActualArgumentIfNotNumeric(self):
57 self.assert_describe_mismatch("was 'bad'", close_to(1.0, 0.5), 'bad')
58
59
60 if __name__ == '__main__':
61 unittest.main()
+0
-72
hamcrest_unit_test/number/ordering_comparison_test.py less more
0 if __name__ == '__main__':
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.library.number.ordering_comparison import *
6
7 from datetime import date
8 from hamcrest_unit_test.matcher_test import MatcherTest
9 import unittest
10
11 __author__ = "Jon Reid"
12 __copyright__ = "Copyright 2011 hamcrest.org"
13 __license__ = "BSD, see License.txt"
14
15
16 class OrderingComparisonTest(MatcherTest):
17
18 def testComparesObjectsForGreaterThan(self):
19 self.assert_matches('match', greater_than(1), 2)
20 self.assert_does_not_match('no match', greater_than(1), 1)
21
22 def testComparesObjectsForLessThan(self):
23 self.assert_matches('match', less_than(1), 0)
24 self.assert_does_not_match('no match', less_than(1), 1)
25
26 def testComparesObjectsForGreaterThanOrEqualTo(self):
27 self.assert_matches('match', greater_than_or_equal_to(1), 2)
28 self.assert_matches('match', greater_than_or_equal_to(1), 1)
29 self.assert_does_not_match('no match', greater_than_or_equal_to(1), 0)
30
31 def testComparesObjectsForLessThanOrEqualTo(self):
32 self.assert_matches('match', less_than_or_equal_to(1), 0)
33 self.assert_matches('match', less_than_or_equal_to(1), 1)
34 self.assert_does_not_match('no match', less_than_or_equal_to(1), 2)
35
36 def testSupportsDifferentTypesOfComparableObjects(self):
37 self.assert_matches('strings', greater_than('bb'), 'cc')
38 self.assert_matches('dates', less_than(date.today()), date.min)
39
40 def testHasAReadableDescription(self):
41 self.assert_description('a value greater than <1>', greater_than(1))
42 self.assert_description('a value greater than or equal to <1>',
43 greater_than_or_equal_to(1))
44 self.assert_description('a value less than <1>', less_than(1))
45 self.assert_description('a value less than or equal to <1>',
46 less_than_or_equal_to(1))
47
48 def testSuccessfulMatchDoesNotGenerateMismatchDescription(self):
49 self.assert_no_mismatch_description(greater_than(1), 2)
50 self.assert_no_mismatch_description(less_than(1), 0)
51 self.assert_no_mismatch_description(greater_than_or_equal_to(1), 1)
52 self.assert_no_mismatch_description(less_than_or_equal_to(1), 1)
53
54 def testMismatchDescription(self):
55 self.assert_mismatch_description("was <0>", greater_than(1), 0)
56 self.assert_mismatch_description("was <2>", less_than(1), 2)
57 self.assert_mismatch_description("was <0>",
58 greater_than_or_equal_to(1), 0)
59 self.assert_mismatch_description("was <2>",
60 less_than_or_equal_to(1), 2)
61
62 def testDescribeMismatch(self):
63 self.assert_describe_mismatch("was <0>", greater_than(1), 0)
64 self.assert_describe_mismatch("was <2>", less_than(1), 2)
65 self.assert_describe_mismatch("was <0>",
66 greater_than_or_equal_to(1), 0)
67 self.assert_describe_mismatch("was <2>", less_than_or_equal_to(1), 2)
68
69
70 if __name__ == '__main__':
71 unittest.main()
+0
-0
hamcrest_unit_test/object/__init__.py less more
(Empty file)
+0
-76
hamcrest_unit_test/object/haslength_test.py less more
0 if __name__ == '__main__':
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.library.object.haslength import *
6
7 from hamcrest.core.core.isequal import equal_to
8 from hamcrest.library.number.ordering_comparison import greater_than
9 from hamcrest_unit_test.matcher_test import MatcherTest
10 import unittest
11
12 __author__ = "Jon Reid"
13 __copyright__ = "Copyright 2011 hamcrest.org"
14 __license__ = "BSD, see License.txt"
15
16
17 class FakeWithLen(object):
18
19 def __init__(self, len):
20 self.len = len
21
22 def __len__(self):
23 return self.len
24
25 def __str__(self):
26 return 'FakeWithLen'
27
28
29 class FakeWithoutLen(object):
30
31 def __str__(self):
32 return 'FakeWithoutLen'
33
34
35 class HasLengthTest(MatcherTest):
36
37 def testPassesResultOfLenToNestedMatcher(self):
38 self.assert_matches('equal', has_length(equal_to(42)), FakeWithLen(42))
39 self.assert_does_not_match('unequal',
40 has_length(equal_to(42)), FakeWithLen(1))
41
42 def testProvidesConvenientShortcutForHasLengthEqualTo(self):
43 self.assert_matches('equal', has_length(42), FakeWithLen(42))
44 self.assert_does_not_match('unequal', has_length(42), FakeWithLen(1))
45
46 def testDoesNotMatchObjectWithoutLen(self):
47 self.assert_does_not_match('no length', has_length(42), object())
48
49 def testHasReadableDescription(self):
50 self.assert_description('an object with length of a value greater than <5>',
51 has_length(greater_than(5)))
52
53 def testSuccessfulMatchDoesNotGenerateMismatchDescription(self):
54 self.assert_no_mismatch_description(has_length(3), 'foo')
55
56 def testMismatchDescriptionForItemWithWrongLength(self):
57 self.assert_mismatch_description('was <FakeWithLen> with length of <4>',
58 has_length(3), FakeWithLen(4))
59
60 def testMismatchDescriptionForItemWithoutLength(self):
61 self.assert_mismatch_description("was <FakeWithoutLen>",
62 has_length(3), FakeWithoutLen())
63
64 def testDescribeMismatchForItemWithWrongLength(self):
65 self.assert_describe_mismatch('was <FakeWithLen> with length of <4>',
66 has_length(3), FakeWithLen(4))
67
68 def testDescribeMismatchForItemWithoutLength(self):
69 self.assert_describe_mismatch("was <FakeWithoutLen>",
70 has_length(3), FakeWithoutLen())
71
72
73
74 if __name__ == '__main__':
75 unittest.main()
+0
-127
hamcrest_unit_test/object/hasproperty_test.py less more
0 if __name__ == '__main__':
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4 import sys
5 print '\n'.join(sys.path)
6
7 from hamcrest.library.object.hasproperty import *
8
9 from hamcrest.core.core.isequal import equal_to
10 from hamcrest_unit_test.matcher_test import MatcherTest
11 import unittest
12
13 __author__ = "Chris Rose"
14 __copyright__ = "Copyright 2011 hamcrest.org"
15 __license__ = "BSD, see License.txt"
16
17 class OnePropertyOldStyle:
18
19 field = 'value'
20
21 class OnePropertyNewStyle(object):
22
23 field = 'value'
24
25 def __repr__(self):
26 return 'OnePropertyNewStyle'
27
28 def __str__(self):
29 return repr(self)
30
31 class OverridingOldStyle:
32
33 def __getattr__(self, name):
34 if name != 'field':
35 raise AttributeError(name)
36 return 'value'
37
38 class OverridingNewStyleGetAttr(object):
39
40 def __getattr__(self, name):
41 if name != 'field':
42 raise AttributeError(name)
43 return 'value'
44
45 class OverridingNewStyleGetAttribute(object):
46
47 def __getattr__(self, name):
48 if name != 'field':
49 raise AttributeError(name)
50 return 'value'
51
52 class HasPropertyTest(MatcherTest):
53
54 def testHasPropertyWithoutValueMatcher(self):
55 self.assert_matches('old-style direct',
56 has_property('field'), OnePropertyOldStyle())
57 self.assert_matches('old-style direct',
58 has_property('field'), OnePropertyNewStyle())
59 self.assert_matches('old-style direct',
60 has_property('field'), OverridingOldStyle())
61 self.assert_matches('old-style direct',
62 has_property('field'), OverridingNewStyleGetAttr())
63 self.assert_matches('old-style direct',
64 has_property('field'), OverridingNewStyleGetAttribute())
65
66 def testHasPropertyWithoutValueMatcherNegative(self):
67 self.assert_does_not_match('old-style direct',
68 has_property('not_there'), OnePropertyOldStyle())
69 self.assert_does_not_match('old-style direct',
70 has_property('not_there'), OnePropertyNewStyle())
71 self.assert_does_not_match('old-style direct',
72 has_property('not_there'), OverridingOldStyle())
73 self.assert_does_not_match('old-style direct',
74 has_property('not_there'), OverridingNewStyleGetAttr())
75 self.assert_does_not_match('old-style direct',
76 has_property('not_there'), OverridingNewStyleGetAttribute())
77
78 def testHasPropertyWithValueMatcher(self):
79 self.assert_matches('old-style direct',
80 has_property('field', 'value'), OnePropertyOldStyle())
81 self.assert_matches('old-style direct',
82 has_property('field', 'value'), OnePropertyNewStyle())
83 self.assert_matches('old-style direct',
84 has_property('field', 'value'), OverridingOldStyle())
85 self.assert_matches('old-style direct',
86 has_property('field', 'value'), OverridingNewStyleGetAttr())
87 self.assert_matches('old-style direct',
88 has_property('field', 'value'), OverridingNewStyleGetAttribute())
89
90 def testHasPropertyWithValueMatcherNegative(self):
91 self.assert_does_not_match('old-style direct',
92 has_property('field', 'not the value'), OnePropertyOldStyle())
93 self.assert_does_not_match('old-style direct',
94 has_property('field', 'not the value'), OnePropertyNewStyle())
95 self.assert_does_not_match('old-style direct',
96 has_property('field', 'not the value'), OverridingOldStyle())
97 self.assert_does_not_match('old-style direct',
98 has_property('field', 'not the value'), OverridingNewStyleGetAttr())
99 self.assert_does_not_match('old-style direct',
100 has_property('field', 'not the value'), OverridingNewStyleGetAttribute())
101
102 def testDescription(self):
103 self.assert_description("an object with a property 'field' matching ANYTHING",
104 has_property('field'))
105 self.assert_description("an object with a property 'field' matching 'value'",
106 has_property('field', 'value'))
107
108 def testDescribeMissingProperty(self):
109 self.assert_mismatch_description("<OnePropertyNewStyle> did not have the 'not_there' property",
110 has_property('not_there'), OnePropertyNewStyle())
111
112 def testDescribePropertyValueMismatch(self):
113 self.assert_mismatch_description("property 'field' was 'value'",
114 has_property('field', 'another_value'), OnePropertyNewStyle())
115
116 def testMismatchDescription(self):
117 self.assert_describe_mismatch("<OnePropertyNewStyle> did not have the 'not_there' property",
118 has_property('not_there'),
119 OnePropertyNewStyle())
120
121 def testNoMismatchDescriptionOnMatch(self):
122 self.assert_no_mismatch_description(has_property('field', 'value'), OnePropertyNewStyle())
123
124
125 if __name__ == '__main__':
126 unittest.main()
+0
-52
hamcrest_unit_test/object/hasstring_test.py less more
0 if __name__ == '__main__':
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.library.object.hasstring import *
6
7 from hamcrest.core.core.isequal import equal_to
8 from hamcrest_unit_test.matcher_test import MatcherTest
9 import unittest
10
11 __author__ = "Jon Reid"
12 __copyright__ = "Copyright 2011 hamcrest.org"
13 __license__ = "BSD, see License.txt"
14
15
16 class FakeWithStr(object):
17
18 def __str__(self):
19 return 'FakeWithStr'
20
21
22 class HasStringTest(MatcherTest):
23
24 def testPassesResultOfToStrToNestedMatcher(self):
25 self.assert_matches('equal',
26 has_string(equal_to('FakeWithStr')), FakeWithStr())
27 self.assert_does_not_match('unequal',
28 has_string(equal_to('FakeWithStr')), 3)
29
30 def testProvidesConvenientShortcutForHasStringEqualTo(self):
31 self.assert_matches('equal', has_string('FakeWithStr'), FakeWithStr())
32 self.assert_does_not_match('unequal', has_string('FakeWithStr'), 3)
33
34 def testHasReadableDescription(self):
35 self.assert_description("an object with str 'foo'", has_string('foo'))
36
37 def testSuccessfulMatchDoesNotGenerateMismatchDescription(self):
38 self.assert_no_mismatch_description(has_string('FakeWithStr'),
39 FakeWithStr())
40
41 def testMismatchDescription(self):
42 self.assert_mismatch_description("was <FakeWithStr>",
43 has_string('foo'), FakeWithStr())
44
45 def testDescribeMismatchDescription(self):
46 self.assert_describe_mismatch("was <FakeWithStr>",
47 has_string('foo'), FakeWithStr())
48
49
50 if __name__ == '__main__':
51 unittest.main()
+0
-8
hamcrest_unit_test/object_import.py less more
0 from hamcrest import *
1
2 try:
3 class MyTest(object):
4 pass
5 except TypeError:
6 print 'Object class defined at ' + getattr(object, '__file__', 'NOWHERE')
7 raise
+0
-58
hamcrest_unit_test/string_description_test.py less more
0 import sys
1 if __name__ == "__main__":
2 sys.path.insert(0, '..')
3
4 from hamcrest.core.string_description import *
5
6 from hamcrest.core.selfdescribing import SelfDescribing
7 import re
8 try:
9 import unittest2 as unittest
10 except ImportError:
11 import unittest
12
13 __author__ = "Jon Reid"
14 __copyright__ = "Copyright 2011 hamcrest.org"
15 __license__ = "BSD, see License.txt"
16
17
18 class FakeSelfDescribing(SelfDescribing):
19
20 def describe_to(self, description):
21 description.append_text('DESCRIPTION')
22
23
24 class StringDescriptionTest(unittest.TestCase):
25
26 def setUp(self):
27 self.description = StringDescription()
28
29 def testLetsSelfDescribingObjectDescribeItself(self):
30 self.description.append_description_of(FakeSelfDescribing())
31 self.assertEqual('DESCRIPTION', str(self.description))
32
33 def testDescribesStringInQuotes(self):
34 self.description.append_description_of('FOO')
35 self.assertEqual("'FOO'", str(self.description))
36
37 def testWrapsNonSelfDescribingObjectInAngleBrackets(self):
38 self.description.append_description_of(42)
39 self.assertEqual('<42>', str(self.description))
40
41 def testShouldNotAddAngleBracketsIfObjectDescriptionAlreadyHasThem(self):
42 self.description.append_description_of(object())
43 expected = re.compile("<object object at 0x[0-9a-fA-F]+>")
44 self.assertTrue(expected.match(str(self.description)))
45
46 @unittest.skipIf(sys.version_info >= (3,), "Describe unicode strings doesn't malform in Python 3")
47 def testDescribeUnicodeStringAsBytes(self):
48 self.description.append_description_of(u'\u05d0')
49 self.assertEqual("u'\\u05d0'", str(self.description))
50
51 @unittest.skipUnless(sys.version_info >= (3,), "Describe unicode strings only malforms in Python 2")
52 def testDescribeUnicodeStringAsUnicode(self):
53 self.description.append_description_of(u'\u05d0')
54 self.assertEqual(u"'\u05d0'", str(self.description))
55
56 if __name__ == "__main__":
57 unittest.main()
+0
-0
hamcrest_unit_test/text/__init__.py less more
(Empty file)
+0
-63
hamcrest_unit_test/text/isequal_ignoring_case_test.py less more
0 if __name__ == '__main__':
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.library.text.isequal_ignoring_case import equal_to_ignoring_case
6
7 from hamcrest_unit_test.matcher_test import MatcherTest
8 import unittest
9
10 __author__ = "Jon Reid"
11 __copyright__ = "Copyright 2011 hamcrest.org"
12 __license__ = "BSD, see License.txt"
13
14
15 matcher = equal_to_ignoring_case('heLLo')
16
17 class IsEqualIgnoringCaseTest(MatcherTest):
18
19 def testIgnoresCaseOfCharsInString(self):
20 self.assert_matches('all upper', matcher, 'HELLO')
21 self.assert_matches('all lower', matcher, 'hello')
22 self.assert_matches('mixed up', matcher, 'HelLo')
23
24 self.assert_does_not_match('no match', matcher, 'bye')
25
26 def testFailsIfAdditionalWhitespaceIsPresent(self):
27 self.assert_does_not_match('whitespace suffix', matcher, 'heLLo ')
28 self.assert_does_not_match('whitespace prefix', matcher, ' heLLo')
29
30 def testMatcherCreationRequiresString(self):
31 self.assertRaises(TypeError, equal_to_ignoring_case, 3)
32
33 def testFailsIfMatchingAgainstNonString(self):
34 self.assert_does_not_match('non-string', matcher, object())
35
36 def testCanApplyUnicodeStringToUnicodeMatcher(self):
37 self.assert_matches('unicode-unicode',
38 equal_to_ignoring_case(u'heLLo'), u'HelLo')
39
40 def testCanApplyPlainStringToUnicodeMatcher(self):
41 self.assert_matches('unicode-ascii',
42 equal_to_ignoring_case(u'heLLo'), 'HelLo')
43
44 def testCanApplyUnicodeStringToPlainMatcher(self):
45 self.assert_matches('ascii-unicode',
46 equal_to_ignoring_case('heLLo'), u'HelLo')
47
48 def testHasAReadableDescription(self):
49 self.assert_description("'heLLo' ignoring case", matcher)
50
51 def testSuccessfulMatchDoesNotGenerateMismatchDescription(self):
52 self.assert_no_mismatch_description(matcher, 'hello')
53
54 def testMismatchDescription(self):
55 self.assert_mismatch_description("was 'bad'", matcher, 'bad')
56
57 def testDescribeMismatch(self):
58 self.assert_describe_mismatch("was 'bad'", matcher, 'bad')
59
60
61 if __name__ == '__main__':
62 unittest.main()
+0
-75
hamcrest_unit_test/text/isequal_ignoring_whitespace_test.py less more
0 if __name__ == '__main__':
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.library.text.isequal_ignoring_whitespace import *
6
7 from hamcrest_unit_test.matcher_test import MatcherTest
8 import unittest
9
10 __author__ = "Jon Reid"
11 __copyright__ = "Copyright 2011 hamcrest.org"
12 __license__ = "BSD, see License.txt"
13
14
15 matcher = equal_to_ignoring_whitespace('Hello World how\n are we? ')
16
17 class IsEqualIgnoringWhiteSpaceTest(MatcherTest):
18
19 def testPassesIfWordsAreSameButWhitespaceDiffers(self):
20 self.assert_matches('less whitespace',
21 matcher, 'Hello World how are we?')
22 self.assert_matches('more whitespace',
23 matcher, ' Hello World how are \n\n\twe?')
24
25 def testFailsIfTextOtherThanWhitespaceDiffers(self):
26 self.assert_does_not_match('wrong word',
27 matcher, 'Hello PLANET how are we?')
28 self.assert_does_not_match('incomplete',
29 matcher, 'Hello World how are we')
30
31 def testFailsIfWhitespaceIsAddedOrRemovedInMidWord(self):
32 self.assert_does_not_match('need whitespace between Hello and World',
33 matcher, 'HelloWorld how are we?')
34 self.assert_does_not_match('wrong whitespace within World',
35 matcher, 'Hello Wo rld how are we?')
36
37 def testMatcherCreationRequiresString(self):
38 self.assertRaises(TypeError, equal_to_ignoring_whitespace, 3)
39
40 def testFailsIfMatchingAgainstNonString(self):
41 self.assert_does_not_match('non-string', matcher, object())
42
43 def testCanApplyUnicodeStringToUnicodeMatcher(self):
44 self.assert_matches('unicode-unicode',
45 equal_to_ignoring_whitespace(u'foo\nbar'),
46 u'foo bar')
47
48 def testCanApplyPlainStringToUnicodeMatcher(self):
49 self.assert_matches('unicode-ascii',
50 equal_to_ignoring_whitespace(u'foo\nbar'),
51 'foo bar')
52
53 def testCanApplyUnicodeStringToPlainMatcher(self):
54 self.assert_matches('ascii-unicode',
55 equal_to_ignoring_whitespace('foo\n bar'),
56 u'foo bar')
57
58 def testDescribesItselfAsIgnoringWhiteSpace(self):
59 self.assert_description("'foo\\nbar' ignoring whitespace",
60 equal_to_ignoring_whitespace('foo\nbar'))
61
62 def testSuccessfulMatchDoesNotGenerateMismatchDescription(self):
63 self.assert_no_mismatch_description(
64 equal_to_ignoring_whitespace('foo\nbar'), 'foo bar')
65
66 def testMismatchDescription(self):
67 self.assert_mismatch_description("was 'bad'", matcher, 'bad')
68
69 def testDescribeMismatch(self):
70 self.assert_describe_mismatch("was 'bad'", matcher, 'bad')
71
72
73 if __name__ == '__main__':
74 unittest.main()
+0
-66
hamcrest_unit_test/text/stringcontains_test.py less more
0 if __name__ == '__main__':
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.library.text.stringcontains import *
6 from hamcrest_unit_test.matcher_test import MatcherTest
7 import unittest
8
9 __author__ = "Jon Reid"
10 __copyright__ = "Copyright 2011 hamcrest.org"
11 __license__ = "BSD, see License.txt"
12
13
14 EXCERPT = 'EXCERPT'
15 matcher = contains_string(EXCERPT)
16
17 class StringContainsTest(MatcherTest):
18
19 def testEvaluatesToTrueIfArgumentContainsSpecifiedSubstring(self):
20 self.assert_matches('excerpt at beginning', matcher, EXCERPT + 'END')
21 self.assert_matches('excerpt at end', matcher, 'START' + EXCERPT)
22 self.assert_matches('excerpt in middle',
23 matcher, 'START' + EXCERPT + 'END')
24 self.assert_matches('excerpt repeated', matcher, EXCERPT + EXCERPT)
25
26 self.assert_does_not_match('excerpt not in string',matcher, 'whatever')
27 self.assert_does_not_match('only part of excerpt',matcher, EXCERPT[1:])
28
29 def testEvaluatesToTrueIfArgumentIsEqualToSubstring(self):
30 self.assert_matches('excerpt is entire string', matcher, EXCERPT)
31
32 def testMatcherCreationRequiresString(self):
33 self.assertRaises(TypeError, contains_string, 3)
34
35 def testFailsIfMatchingAgainstNonString(self):
36 self.assert_does_not_match('non-string', matcher, object())
37
38 def testCanApplyUnicodeStringToUnicodeMatcher(self):
39 self.assert_matches('unicode-unicode',
40 contains_string(u'bar'), u'foo bar baz')
41
42 def testCanApplyPlainStringToUnicodeMatcher(self):
43 self.assert_matches('unicode-ascii',
44 contains_string(u'bar'), 'foo bar baz')
45
46 def testCanApplyUnicodeStringToPlainMatcher(self):
47 self.assert_matches('ascii-unicode',
48 contains_string('bar'), u'foo bar baz')
49
50 def testHasAReadableDescription(self):
51 self.assert_description("a string containing 'EXCERPT'", matcher)
52
53 def testSuccessfulMatchDoesNotGenerateMismatchDescription(self):
54 self.assert_no_mismatch_description(matcher, EXCERPT)
55
56 def testMismatchDescription(self):
57 self.assert_mismatch_description("was 'bad'", matcher, 'bad')
58
59 def testDescribeMismatch(self):
60 self.assert_describe_mismatch("was 'bad'", matcher, 'bad')
61
62
63
64 if __name__ == '__main__':
65 unittest.main()
+0
-50
hamcrest_unit_test/text/stringcontainsinorder_test.py less more
0 if __name__ == '__main__':
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.library.text.stringcontainsinorder import *
6
7 from hamcrest.core.string_description import StringDescription
8 from hamcrest_unit_test.matcher_test import MatcherTest
9 import unittest
10
11 __author__ = "Romilly Cocking"
12 __copyright__ = "Copyright 2011 hamcrest.org"
13 __license__ = "BSD, see License.txt"
14
15
16 matcher = string_contains_in_order('string one', 'string two', 'string three')
17
18 class StringContainsInOrderTest(MatcherTest):
19
20 def testMatchesIfOrderIsCorrect(self):
21 self.assert_matches('correct order', matcher,
22 'string one then string two followed by string three')
23
24 def testDoesNotMatchIfOrderIsIncorrect(self):
25 self.assert_does_not_match('incorrect order', matcher,
26 'string two then string one followed by string three')
27
28 def testDoesNotMatchIfExpectedSubstringsAreMissing(self):
29 self.assert_does_not_match('missing string one', matcher, 'string two then string three')
30 self.assert_does_not_match('missing string two', matcher, 'string one then string three')
31 self.assert_does_not_match('missing string three', matcher, 'string one then string two')
32
33 def testMatcherCreationRequiresString(self):
34 self.assertRaises(TypeError, string_contains_in_order, 3)
35
36 def testFailsIfMatchingAgainstNonString(self):
37 self.assert_does_not_match('non-string', matcher, object())
38
39 def testHasAReadableDescription(self):
40 self.assert_description("a string containing 'string one', 'string two', 'string three' in order", matcher)
41
42 def testSuccessfulMatchDoesNotGenerateMismatchDescription(self):
43 self.assert_no_mismatch_description(matcher, 'string one then string two followed by string three')
44
45 def testMismatchDescription(self):
46 self.assert_mismatch_description("was 'bad'", matcher, 'bad')
47
48 def testDescribeMismatch(self):
49 self.assert_describe_mismatch("was 'bad'", matcher, 'bad')
+0
-69
hamcrest_unit_test/text/stringendswith_test.py less more
0 if __name__ == '__main__':
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.library.text.stringendswith import *
6
7 from hamcrest_unit_test.matcher_test import MatcherTest
8 import unittest
9
10 __author__ = "Jon Reid"
11 __copyright__ = "Copyright 2011 hamcrest.org"
12 __license__ = "BSD, see License.txt"
13
14
15 EXCERPT = 'EXCERPT'
16 matcher = ends_with(EXCERPT)
17
18 class StringEndsWithTest(MatcherTest):
19
20 def testEvaluatesToTrueIfArgumentContainsSpecifiedSubstring(self):
21 self.assert_does_not_match('excerpt at beginning',
22 matcher, EXCERPT + 'END')
23 self.assert_matches('excerpt at end', matcher, 'START' + EXCERPT)
24 self.assert_does_not_match('excerpt in middle',
25 matcher, 'START' + EXCERPT + 'END')
26 self.assert_matches('excerpt repeated', matcher, EXCERPT + EXCERPT)
27
28 self.assert_does_not_match('excerpt not in string',
29 matcher, 'whatever')
30 self.assert_does_not_match('only part of excerpt is at end of string',
31 matcher, EXCERPT[1:])
32
33 def testEvaluatesToTrueIfArgumentIsEqualToSubstring(self):
34 self.assert_matches('excerpt is entire string', matcher, EXCERPT)
35
36 def testMatcherCreationRequiresString(self):
37 self.assertRaises(TypeError, ends_with, 3)
38
39 def testFailsIfMatchingAgainstNonString(self):
40 self.assert_does_not_match('non-string', matcher, object())
41
42 def testCanApplyUnicodeStringToUnicodeMatcher(self):
43 self.assert_matches('unicode-unicode',
44 ends_with(u'baz'), u'foo bar baz')
45
46 def testCanApplyPlainStringToUnicodeMatcher(self):
47 self.assert_matches('unicode-ascii',
48 ends_with(u'baz'), 'foo bar baz')
49
50 def testCanApplyUnicodeStringToPlainMatcher(self):
51 self.assert_matches('ascii-unicode',
52 ends_with(u'baz'), u'foo bar baz')
53
54 def testHasAReadableDescription(self):
55 self.assert_description("a string ending with 'EXCERPT'", matcher)
56
57 def testSuccessfulMatchDoesNotGenerateMismatchDescription(self):
58 self.assert_no_mismatch_description(matcher, EXCERPT)
59
60 def testMismatchDescription(self):
61 self.assert_mismatch_description("was 'bad'", matcher, 'bad')
62
63 def testDescribeMismatch(self):
64 self.assert_describe_mismatch("was 'bad'", matcher, 'bad')
65
66
67 if __name__ == '__main__':
68 unittest.main()
+0
-70
hamcrest_unit_test/text/stringstartswith_test.py less more
0 if __name__ == '__main__':
1 import sys
2 sys.path.insert(0, '..')
3 sys.path.insert(0, '../..')
4
5 from hamcrest.library.text.stringstartswith import *
6
7 from hamcrest.core.assert_that import assert_that
8 from hamcrest.core.core.isnot import is_not
9 from hamcrest_unit_test.matcher_test import MatcherTest
10 import unittest
11
12 __author__ = "Jon Reid"
13 __copyright__ = "Copyright 2011 hamcrest.org"
14 __license__ = "BSD, see License.txt"
15
16
17 EXCERPT = 'EXCERPT'
18 matcher = starts_with(EXCERPT)
19 stringstartswith = starts_with(EXCERPT)
20
21 class StringStartsWithTest(MatcherTest):
22
23 def testEvaluatesToTrueIfArgumentContainsSpecifiedSubstring(self):
24 self.assert_matches('excerpt at beginning', matcher, EXCERPT + 'END')
25 self.assert_does_not_match('excerpt at end',
26 matcher, 'START' + EXCERPT)
27 self.assert_does_not_match('excerpt in middle',
28 matcher, 'START' + EXCERPT + 'END')
29 self.assert_matches('excerpt repeated', matcher, EXCERPT + EXCERPT)
30
31 self.assert_does_not_match('excerpt not in string',matcher, 'whatever')
32 self.assert_does_not_match('only part of excerpt',matcher, EXCERPT[1:])
33
34 def testEvaluatesToTrueIfArgumentIsEqualToSubstring(self):
35 self.assert_matches('excerpt is entire string', matcher, EXCERPT)
36
37 def testMatcherCreationRequiresString(self):
38 self.assertRaises(TypeError, starts_with, 3)
39
40 def testFailsIfMatchingAgainstNonString(self):
41 self.assert_does_not_match('non-string', matcher, object())
42
43 def testCanApplyUnicodeStringToUnicodeMatcher(self):
44 self.assert_matches('unicode-unicode',
45 starts_with(u'foo'), u'foo bar baz')
46
47 def testCanApplyPlainStringToUnicodeMatcher(self):
48 self.assert_matches('unicode-ascii',
49 starts_with(u'foo'), 'foo bar baz')
50
51 def testCanApplyUnicodeStringToPlainMatcher(self):
52 self.assert_matches('ascii-unicode',
53 starts_with(u'foo'), u'foo bar baz')
54
55 def testHasAReadableDescription(self):
56 self.assert_description("a string starting with 'EXCERPT'", matcher)
57
58 def testSuccessfulMatchDoesNotGenerateMismatchDescription(self):
59 self.assert_no_mismatch_description(matcher, EXCERPT)
60
61 def testMismatchDescription(self):
62 self.assert_mismatch_description("was 'bad'", matcher, 'bad')
63
64 def testDescribeMismatch(self):
65 self.assert_describe_mismatch("was 'bad'", matcher, 'bad')
66
67
68 if __name__ == '__main__':
69 unittest.main()
1616
1717 # On Python 3, we can't "from hamcrest import __version__" (get ImportError),
1818 # so we extract the variable assignment and execute it ourselves.
19 fh = open(local('hamcrest/__init__.py'))
19 fh = open(local('src/hamcrest/__init__.py'))
2020 try:
2121 for line in fh:
2222 if re.match('__version__.*', line):
3030 extra_attributes['use_2to3'] = True
3131
3232 params = dict(
33 name = 'PyHamcrest',
34 version = __version__,
35 author = 'Jon Reid',
36 author_email = 'jon.reid@mac.com',
37 description = 'Hamcrest framework for matcher objects',
38 license = 'New BSD',
33 name='PyHamcrest',
34 version=__version__, #flake8:noqa
35 author='Chris Rose',
36 author_email='offline@offby1.net',
37 description='Hamcrest framework for matcher objects',
38 license='New BSD',
3939 platforms=['All'],
40 keywords = 'hamcrest matchers pyunit unit test testing unittest unittesting',
41 url = 'http://code.google.com/p/hamcrest/',
42 download_url = 'http://pypi.python.org/packages/source/P/PyHamcrest/PyHamcrest-%s.tar.gz' % __version__,
43 packages = find_packages(),
44 test_suite = 'hamcrest-unit-test.alltests',
45 provides = ['hamcrest'],
46 long_description=read('README.md'),
47 install_requires=['distribute'],
48 classifiers = [
40 keywords='hamcrest matchers pyunit unit test testing unittest unittesting',
41 url='https://github.com/hamcrest/PyHamcrest',
42 download_url='http://pypi.python.org/packages/source/P/PyHamcrest/PyHamcrest-%s.tar.gz' % __version__,
43 packages=find_packages('src'),
44 package_dir = {'': 'src'},
45 provides=['hamcrest'],
46 long_description=read('README.rst'),
47 install_requires=['setuptools'],
48 classifiers=[
4949 'Development Status :: 5 - Production/Stable',
5050 'Environment :: Console',
5151 'Intended Audience :: Developers',
5555 'Programming Language :: Python :: 2.5',
5656 'Programming Language :: Python :: 2.6',
5757 'Programming Language :: Python :: 2.7',
58 'Programming Language :: Python :: 3.1',
5958 'Programming Language :: Python :: 3.2',
59 'Programming Language :: Python :: 3.3',
6060 'Topic :: Software Development',
6161 'Topic :: Software Development :: Quality Assurance',
6262 'Topic :: Software Development :: Testing',
0 Metadata-Version: 1.1
1 Name: PyHamcrest
2 Version: 1.8.0
3 Summary: Hamcrest framework for matcher objects
4 Home-page: https://github.com/hamcrest/PyHamcrest
5 Author: Chris Rose
6 Author-email: offline@offby1.net
7 License: New BSD
8 Download-URL: http://pypi.python.org/packages/source/P/PyHamcrest/PyHamcrest-1.8.0.tar.gz
9 Description: PyHamcrest
10 ==========
11
12 .. image:: https://pypip.in/v/PyHamcrest/badge.png
13 :alt: Release Status
14 :target: https://crate.io/packages/PyHamcrest
15 .. image:: https://pypip.in/d/PyHamcrest/badge.png
16 :alt: Downloads
17 :target: https://crate.io/packages/PyHamcrest
18 .. image:: https://travis-ci.org/hamcrest/PyHamcrest.png?branch=master
19 :alt: Build Status
20 :target: https://travis-ci.org/hamcrest/PyHamcrest
21
22 Introduction
23 ============
24
25 PyHamcrest is a framework for writing matcher objects, allowing you to
26 declaratively define "match" rules. There are a number of situations where
27 matchers are invaluable, such as UI validation, or data filtering, but it is in
28 the area of writing flexible tests that matchers are most commonly used. This
29 tutorial shows you how to use PyHamcrest for unit testing.
30
31 When writing tests it is sometimes difficult to get the balance right between
32 overspecifying the test (and making it brittle to changes), and not specifying
33 enough (making the test less valuable since it continues to pass even when the
34 thing being tested is broken). Having a tool that allows you to pick out
35 precisely the aspect under test and describe the values it should have, to a
36 controlled level of precision, helps greatly in writing tests that are "just
37 right." Such tests fail when the behavior of the aspect under test deviates
38 from the expected behavior, yet continue to pass when minor, unrelated changes
39 to the behaviour are made.
40
41 Installation
42 ============
43
44 Hamcrest can be installed using the usual Python packaging tools. It depends on
45 distribute, but as long as you have a network connection when you install, the
46 installation process will take care of that for you.
47
48 My first PyHamcrest test
49 ========================
50
51 We'll start by writing a very simple PyUnit test, but instead of using PyUnit's
52 ``assertEqual`` method, we'll use PyHamcrest's ``assert_that`` construct and
53 the standard set of matchers:
54
55 .. code:: python
56
57 from hamcrest import *
58 import unittest
59
60 class BiscuitTest(unittest.TestCase):
61 def testEquals(self):
62 theBiscuit = Biscuit('Ginger')
63 myBiscuit = Biscuit('Ginger')
64 assert_that(theBiscuit, equal_to(myBiscuit))
65
66 if __name__ == '__main__':
67 unittest.main()
68
69 The ``assert_that`` function is a stylized sentence for making a test
70 assertion. In this example, the subject of the assertion is the object
71 ``theBiscuit``, which is the first method parameter. The second method
72 parameter is a matcher for ``Biscuit`` objects, here a matcher that checks one
73 object is equal to another using the Python ``==`` operator. The test passes
74 since the ``Biscuit`` class defines an ``__eq__`` method.
75
76 If you have more than one assertion in your test you can include an identifier
77 for the tested value in the assertion:
78
79 .. code:: python
80
81 assert_that(theBiscuit.getChocolateChipCount(), equal_to(10), 'chocolate chips')
82 assert_that(theBiscuit.getHazelnutCount(), equal_to(3), 'hazelnuts')
83
84 As a convenience, assert_that can also be used to verify a boolean condition:
85
86 .. code:: python
87
88 assert_that(theBiscuit.isCooked(), 'cooked')
89
90 This is equivalent to the ``assert_`` method of unittest.TestCase, but because
91 it's a standalone function, it offers greater flexibility in test writing.
92
93
94 Predefined matchers
95 ===================
96
97 PyHamcrest comes with a library of useful matchers:
98
99 * Object
100
101 * ``equal_to`` - match equal object
102 * ``has_length`` - match ``len()``
103 * ``has_property`` - match value of property with given name
104 * ``has_properties`` - match an object that has all of the given properties.
105 * ``has_string`` - match ``str()``
106 * ``instance_of`` - match object type
107 * ``none``, ``not_none`` - match ``None``, or not ``None``
108 * ``same_instance`` - match same object
109
110 * Number
111
112 * ``close_to`` - match number close to a given value
113 * ``greater_than``, ``greater_than_or_equal_to``, ``less_than``,
114 ``less_than_or_equal_to`` - match numeric ordering
115
116 * Text
117
118 * ``contains_string`` - match part of a string
119 * ``ends_with`` - match the end of a string
120 * ``equal_to_ignoring_case`` - match the complete string but ignore case
121 * ``equal_to_ignoring_whitespace`` - match the complete string but ignore extra whitespace
122 * ``matches_regexp`` - match a regular expression in a string
123 * ``starts_with`` - match the beginning of a string
124 * ``string_contains_in_order`` - match parts of a string, in relative order
125
126 * Logical
127
128 * ``all_of`` - ``and`` together all matchers
129 * ``any_of`` - ``or`` together all matchers
130 * ``anything`` - match anything, useful in composite matchers when you don't care about a particular value
131 * ``is_not`` - negate the matcher
132
133 * Sequence
134
135 * ``contains`` - exactly match the entire sequence
136 * ``contains_inanyorder`` - match the entire sequence, but in any order
137 * ``has_item`` - match if given item appears in the sequence
138 * ``has_items`` - match if all given items appear in the sequence, in any order
139 * ``is_in`` - match if item appears in the given sequence
140 * ``only_contains`` - match if sequence's items appear in given list
141
142 * Dictionary
143
144 * ``has_entries`` - match dictionary with list of key-value pairs
145 * ``has_entry`` - match dictionary containing a key-value pair
146 * ``has_key`` - match dictionary with a key
147 * ``has_value`` - match dictionary with a value
148
149 * Decorator
150
151 * ``calling`` - wrap a callable in a deffered object, for subsequent matching on calling behaviour
152 * ``raises`` - Ensure that a deferred callable raises as expected
153 * ``described_as`` - give the matcher a custom failure description
154 * ``is_`` - decorator to improve readability - see `Syntactic sugar` below
155
156 The arguments for many of these matchers accept not just a matching value, but
157 another matcher, so matchers can be composed for greater flexibility. For
158 example, ``only_contains(less_than(5))`` will match any sequence where every
159 item is less than 5.
160
161
162 Syntactic sugar
163 ===============
164
165 PyHamcrest strives to make your tests as readable as possible. For example, the
166 ``is_`` matcher is a wrapper that doesn't add any extra behavior to the
167 underlying matcher. The following assertions are all equivalent:
168
169 .. code:: python
170
171 assert_that(theBiscuit, equal_to(myBiscuit))
172 assert_that(theBiscuit, is_(equal_to(myBiscuit)))
173 assert_that(theBiscuit, is_(myBiscuit))
174
175 The last form is allowed since ``is_(value)`` wraps most non-matcher arguments
176 with ``equal_to``. But if the argument is a type, it is wrapped with
177 ``instance_of``, so the following are also equivalent:
178
179 .. code:: python
180
181 assert_that(theBiscuit, instance_of(Biscuit))
182 assert_that(theBiscuit, is_(instance_of(Biscuit)))
183 assert_that(theBiscuit, is_(Biscuit))
184
185 *Note that PyHamcrest's ``is_`` matcher is unrelated to Python's ``is``
186 operator. The matcher for object identity is ``same_instance``.*
187
188
189 Writing custom matchers
190 =======================
191
192 PyHamcrest comes bundled with lots of useful matchers, but you'll probably find
193 that you need to create your own from time to time to fit your testing needs.
194 This commonly occurs when you find a fragment of code that tests the same set
195 of properties over and over again (and in different tests), and you want to
196 bundle the fragment into a single assertion. By writing your own matcher you'll
197 eliminate code duplication and make your tests more readable!
198
199 Let's write our own matcher for testing if a calendar date falls on a Saturday.
200 This is the test we want to write:
201
202 .. code:: python
203
204 def testDateIsOnASaturday(self):
205 d = datetime.date(2008, 04, 26)
206 assert_that(d, is_(on_a_saturday()))
207
208 And here's the implementation:
209
210 .. code:: python
211
212 from hamcrest.core.base_matcher import BaseMatcher
213 from hamcrest.core.helpers.hasmethod import hasmethod
214
215 class IsGivenDayOfWeek(BaseMatcher):
216
217 def __init__(self, day):
218 self.day = day # Monday is 0, Sunday is 6
219
220 def _matches(self, item):
221 if not hasmethod(item, 'weekday'):
222 return False
223 return item.weekday() == self.day
224
225 def describe_to(self, description):
226 day_as_string = ['Monday', 'Tuesday', 'Wednesday', 'Thursday',
227 'Friday', 'Saturday', 'Sunday']
228 description.append_text('calendar date falling on ') \
229 .append_text(day_as_string[self.day])
230
231 def on_a_saturday():
232 return IsGivenDayOfWeek(5)
233
234 For our Matcher implementation we implement the ``_matches`` method - which
235 calls the ``weekday`` method after confirming that the argument (which may not
236 be a date) has such a method - and the ``describe_to`` method - which is used
237 to produce a failure message when a test fails. Here's an example of how the
238 failure message looks:
239
240 .. code:: python
241
242 assert_that(datetime.date(2008, 04, 06), is_(on_a_saturday()))
243
244 fails with the message::
245
246 AssertionError:
247 Expected: is calendar date falling on Saturday
248 got: <2008-04-06>
249
250 Let's say this matcher is saved in a module named ``isgivendayofweek``. We
251 could use it in our test by importing the factory function ``on_a_saturday``:
252
253 .. code:: python
254
255 from hamcrest import *
256 import unittest
257 from isgivendayofweek import on_a_saturday
258
259 class DateTest(unittest.TestCase):
260 def testDateIsOnASaturday(self):
261 d = datetime.date(2008, 04, 26)
262 assert_that(d, is_(on_a_saturday()))
263
264 if __name__ == '__main__':
265 unittest.main()
266
267 Even though the ``on_a_saturday`` function creates a new matcher each time it
268 is called, you should not assume this is the only usage pattern for your
269 matcher. Therefore you should make sure your matcher is stateless, so a single
270 instance can be reused between matches.
271
272
273 More resources
274 ==============
275
276 * Documentation_
277 * Package_
278 * Sources_
279 * Hamcrest_
280
281 .. _Documentation: http://readthedocs.org/docs/pyhamcrest/en/V1.7.1/
282 .. _Package: http://pypi.python.org/pypi/PyHamcrest
283 .. _Sources: https://github.com/hamcrest/PyHamcrest
284 .. _Hamcrest: http://hamcrest.org
285
286 Keywords: hamcrest matchers pyunit unit test testing unittest unittesting
287 Platform: All
288 Classifier: Development Status :: 5 - Production/Stable
289 Classifier: Environment :: Console
290 Classifier: Intended Audience :: Developers
291 Classifier: License :: OSI Approved :: BSD License
292 Classifier: Natural Language :: English
293 Classifier: Operating System :: OS Independent
294 Classifier: Programming Language :: Python :: 2.5
295 Classifier: Programming Language :: Python :: 2.6
296 Classifier: Programming Language :: Python :: 2.7
297 Classifier: Programming Language :: Python :: 3.2
298 Classifier: Programming Language :: Python :: 3.3
299 Classifier: Topic :: Software Development
300 Classifier: Topic :: Software Development :: Quality Assurance
301 Classifier: Topic :: Software Development :: Testing
302 Provides: hamcrest
0 CHANGES.txt
1 LICENSE.txt
2 MANIFEST.in
3 README.rst
4 setup.cfg
5 setup.py
6 examples/CustomDateMatcher.py
7 examples/ExampleWithAssertThat.py
8 src/PyHamcrest.egg-info/PKG-INFO
9 src/PyHamcrest.egg-info/SOURCES.txt
10 src/PyHamcrest.egg-info/dependency_links.txt
11 src/PyHamcrest.egg-info/requires.txt
12 src/PyHamcrest.egg-info/top_level.txt
13 src/hamcrest/__init__.py
14 src/hamcrest/core/__init__.py
15 src/hamcrest/core/assert_that.py
16 src/hamcrest/core/base_description.py
17 src/hamcrest/core/base_matcher.py
18 src/hamcrest/core/compat.py
19 src/hamcrest/core/description.py
20 src/hamcrest/core/matcher.py
21 src/hamcrest/core/selfdescribing.py
22 src/hamcrest/core/selfdescribingvalue.py
23 src/hamcrest/core/string_description.py
24 src/hamcrest/core/core/__init__.py
25 src/hamcrest/core/core/allof.py
26 src/hamcrest/core/core/anyof.py
27 src/hamcrest/core/core/described_as.py
28 src/hamcrest/core/core/is_.py
29 src/hamcrest/core/core/isanything.py
30 src/hamcrest/core/core/isequal.py
31 src/hamcrest/core/core/isinstanceof.py
32 src/hamcrest/core/core/isnone.py
33 src/hamcrest/core/core/isnot.py
34 src/hamcrest/core/core/issame.py
35 src/hamcrest/core/core/raises.py
36 src/hamcrest/core/helpers/__init__.py
37 src/hamcrest/core/helpers/hasmethod.py
38 src/hamcrest/core/helpers/wrap_matcher.py
39 src/hamcrest/library/__init__.py
40 src/hamcrest/library/collection/__init__.py
41 src/hamcrest/library/collection/is_empty.py
42 src/hamcrest/library/collection/isdict_containing.py
43 src/hamcrest/library/collection/isdict_containingentries.py
44 src/hamcrest/library/collection/isdict_containingkey.py
45 src/hamcrest/library/collection/isdict_containingvalue.py
46 src/hamcrest/library/collection/isin.py
47 src/hamcrest/library/collection/issequence_containing.py
48 src/hamcrest/library/collection/issequence_containinginanyorder.py
49 src/hamcrest/library/collection/issequence_containinginorder.py
50 src/hamcrest/library/collection/issequence_onlycontaining.py
51 src/hamcrest/library/integration/__init__.py
52 src/hamcrest/library/integration/match_equality.py
53 src/hamcrest/library/number/__init__.py
54 src/hamcrest/library/number/iscloseto.py
55 src/hamcrest/library/number/ordering_comparison.py
56 src/hamcrest/library/object/__init__.py
57 src/hamcrest/library/object/haslength.py
58 src/hamcrest/library/object/hasproperty.py
59 src/hamcrest/library/object/hasstring.py
60 src/hamcrest/library/text/__init__.py
61 src/hamcrest/library/text/isequal_ignoring_case.py
62 src/hamcrest/library/text/isequal_ignoring_whitespace.py
63 src/hamcrest/library/text/stringcontains.py
64 src/hamcrest/library/text/stringcontainsinorder.py
65 src/hamcrest/library/text/stringendswith.py
66 src/hamcrest/library/text/stringmatches.py
67 src/hamcrest/library/text/stringstartswith.py
68 src/hamcrest/library/text/substringmatcher.py
0 from core import *
1 from library import *
2
3 __version__ = "1.8.0"
4 __author__ = "Chris Rose"
5 __copyright__ = "Copyright 2013 hamcrest.org"
6 __license__ = "BSD, see License.txt"
0 from assert_that import assert_that
1 from core import *
2
3 __author__ = "Jon Reid"
4 __copyright__ = "Copyright 2011 hamcrest.org"
5 __license__ = "BSD, see License.txt"
0 from matcher import Matcher
1 from string_description import StringDescription
2
3 __author__ = "Jon Reid"
4 __copyright__ = "Copyright 2011 hamcrest.org"
5 __license__ = "BSD, see License.txt"
6 # unittest integration; hide these frames from tracebacks
7 __unittest = True
8 # py.test integration; hide these frames from tracebacks
9 __tracebackhide__ = True
10
11 def assert_that(arg1, arg2=None, arg3=''):
12 """Asserts that actual value satisfies matcher. (Can also assert plain
13 boolean condition.)
14
15 :param actual: The object to evaluate as the actual value.
16 :param matcher: The matcher to satisfy as the expected condition.
17 :param reason: Optional explanation to include in failure description.
18
19 ``assert_that`` passes the actual value to the matcher for evaluation. If
20 the matcher is not satisfied, an exception is thrown describing the
21 mismatch.
22
23 ``assert_that`` is designed to integrate well with PyUnit and other unit
24 testing frameworks. The exception raised for an unmet assertion is an
25 :py:exc:`AssertionError`, which PyUnit reports as a test failure.
26
27 With a different set of parameters, ``assert_that`` can also verify a
28 boolean condition:
29
30 .. function:: assert_that(assertion[, reason])
31
32 :param assertion: Boolean condition to verify.
33 :param reason: Optional explanation to include in failure description.
34
35 This is equivalent to the :py:meth:`~unittest.TestCase.assertTrue` method
36 of :py:class:`unittest.TestCase`, but offers greater flexibility in test
37 writing by being a standalone function.
38
39 """
40 if isinstance(arg2, Matcher):
41 _assert_match(actual=arg1, matcher=arg2, reason=arg3)
42 else:
43 _assert_bool(assertion=arg1, reason=arg2)
44
45
46 def _assert_match(actual, matcher, reason):
47 if not matcher.matches(actual):
48 description = StringDescription()
49 description.append_text(reason) \
50 .append_text('\nExpected: ') \
51 .append_description_of(matcher) \
52 .append_text('\n but: ')
53 matcher.describe_mismatch(actual, description)
54 description.append_text('\n')
55 raise AssertionError(str(description))
56
57
58 def _assert_bool(assertion, reason=None):
59 if not assertion:
60 if not reason:
61 reason = 'Assertion failed'
62 raise AssertionError(reason)
0 from description import Description
1 from selfdescribingvalue import SelfDescribingValue
2 from helpers.hasmethod import hasmethod
3
4 import warnings
5
6 __author__ = "Jon Reid"
7 __copyright__ = "Copyright 2011 hamcrest.org"
8 __license__ = "BSD, see License.txt"
9
10
11 class BaseDescription(Description):
12 """Base class for all :py:class:`~hamcrest.core.description.Description`
13 implementations.
14
15 """
16
17 def append_text(self, text):
18 self.append(text)
19 return self
20
21 def append_description_of(self, value):
22 if hasmethod(value, 'describe_to'):
23 value.describe_to(self)
24 elif isinstance(value, str):
25 self.append_string_in_python_syntax(value)
26 elif isinstance(value, unicode):
27 self.append(repr(value))
28 else:
29 description = str(value)
30 if description[:1] == '<' and description[-1:] == '>':
31 self.append(description)
32 else:
33 self.append('<')
34 self.append(description)
35 self.append('>')
36 return self
37
38 def append_value(self, value):
39 warnings.warn('Call append_description_of instead of append_value',
40 DeprecationWarning)
41 if isinstance(value, str):
42 self.append_string_in_python_syntax(value)
43 else:
44 self.append('<')
45 self.append(str(value))
46 self.append('>')
47 return self
48
49 def append_value_list(self, start, separator, end, list):
50 warnings.warn('Call append_list instead of append_value_list',
51 DeprecationWarning)
52 return self.append_list(start, separator, end,
53 map(SelfDescribingValue, list))
54
55 def append_list(self, start, separator, end, list):
56 separate = False
57
58 self.append(start)
59 for item in list:
60 if separate:
61 self.append(separator)
62 self.append_description_of(item)
63 separate = True
64 self.append(end)
65 return self
66
67 def append(self, string):
68 """Append the string to the description."""
69 raise NotImplementedError('append')
70
71 def append_string_in_python_syntax(self, string):
72 self.append("'")
73 for ch in string:
74 self.append(character_in_python_syntax(ch))
75 self.append("'")
76
77
78 def character_in_python_syntax(ch):
79 if ch == "'":
80 return "\'"
81 elif ch == '\n':
82 return '\\n'
83 elif ch == '\r':
84 return '\\r'
85 elif ch == '\t':
86 return '\\t'
87 else:
88 return ch
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4 from matcher import Matcher
5 from string_description import tostring
6
7
8 class BaseMatcher(Matcher):
9 """Base class for all :py:class:`~hamcrest.core.matcher.Matcher`
10 implementations.
11
12 Most implementations can just implement :py:obj:`_matches`, leaving the
13 handling of any mismatch description to the ``matches`` method. But if it
14 makes more sense to generate the mismatch description during the matching,
15 override :py:meth:`~hamcrest.core.matcher.Matcher.matches` instead.
16
17 """
18
19 def __str__(self):
20 return tostring(self)
21
22 def _matches(self, item):
23 raise NotImplementedError('_matches')
24
25 def matches(self, item, mismatch_description=None):
26 match_result = self._matches(item)
27 if not match_result and mismatch_description:
28 self.describe_mismatch(item, mismatch_description)
29 return match_result
30
31 def describe_mismatch(self, item, mismatch_description):
32 mismatch_description.append_text('was ').append_description_of(item)
0 __author__ = "Per Fagrell"
1 __copyright__ = "Copyright 2013 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4 __all__ = ['is_callable']
5
6 import sys
7
8 # callable was not part of py3k until 3.2, so we create this
9 # generic is_callable to use callable if possible, otherwise
10 # we use generic homebrew.
11 if sys.version_info[0] == 3 and sys.version_info[1] < 2:
12 def is_callable(function):
13 """Return whether the object is callable (i.e., some kind of function)."""
14 if function is None:
15 return False
16 return any("__call__" in klass.__dict__ for klass in type(function).__mro__)
17 else:
18 is_callable = callable
0 """Fundamental matchers of objects and values, and composite matchers."""
1
2 from allof import all_of
3 from anyof import any_of
4 from described_as import described_as
5 from is_ import is_
6 from isanything import anything
7 from isequal import equal_to
8 from isinstanceof import instance_of
9 from isnone import none, not_none
10 from isnot import is_not
11 from issame import same_instance
12 from raises import calling, raises
13
14 __author__ = "Jon Reid"
15 __copyright__ = "Copyright 2011 hamcrest.org"
16 __license__ = "BSD, see License.txt"
0 from hamcrest.core.base_matcher import BaseMatcher
1 from hamcrest.core.helpers.wrap_matcher import wrap_matcher
2
3 __author__ = "Jon Reid"
4 __copyright__ = "Copyright 2011 hamcrest.org"
5 __license__ = "BSD, see License.txt"
6
7
8 class AllOf(BaseMatcher):
9
10 def __init__(self, *matchers):
11 self.matchers = matchers
12
13 def matches(self, item, mismatch_description=None):
14 for matcher in self.matchers:
15 if not matcher.matches(item):
16 if mismatch_description:
17 mismatch_description.append_description_of(matcher) \
18 .append_text(' ')
19 matcher.describe_mismatch(item, mismatch_description)
20 return False
21 return True
22
23 def describe_mismatch(self, item, mismatch_description):
24 self.matches(item, mismatch_description)
25
26 def describe_to(self, description):
27 description.append_list('(', ' and ', ')', self.matchers)
28
29
30 def all_of(*items):
31 """Matches if all of the given matchers evaluate to ``True``.
32
33 :param matcher1,...: A comma-separated list of matchers.
34
35 The matchers are evaluated from left to right using short-circuit
36 evaluation, so evaluation stops as soon as a matcher returns ``False``.
37
38 Any argument that is not a matcher is implicitly wrapped in an
39 :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
40 equality.
41
42 """
43 return AllOf(*[wrap_matcher(item) for item in items])
0 from hamcrest.core.base_matcher import BaseMatcher
1 from hamcrest.core.helpers.wrap_matcher import wrap_matcher
2
3 __author__ = "Jon Reid"
4 __copyright__ = "Copyright 2011 hamcrest.org"
5 __license__ = "BSD, see License.txt"
6
7
8 class AnyOf(BaseMatcher):
9
10 def __init__(self, *matchers):
11 self.matchers = matchers
12
13 def _matches(self, item):
14 for matcher in self.matchers:
15 if matcher.matches(item):
16 return True
17 return False
18
19 def describe_to(self, description):
20 description.append_list('(', ' or ', ')', self.matchers)
21
22
23 def any_of(*items):
24 """Matches if any of the given matchers evaluate to ``True``.
25
26 :param matcher1,...: A comma-separated list of matchers.
27
28 The matchers are evaluated from left to right using short-circuit
29 evaluation, so evaluation stops as soon as a matcher returns ``True``.
30
31 Any argument that is not a matcher is implicitly wrapped in an
32 :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
33 equality.
34
35 """
36 return AnyOf(*[wrap_matcher(item) for item in items])
0 from hamcrest.core.base_matcher import BaseMatcher
1 import re
2
3 __author__ = "Jon Reid"
4 __copyright__ = "Copyright 2011 hamcrest.org"
5 __license__ = "BSD, see License.txt"
6
7
8 ARG_PATTERN = re.compile('%([0-9]+)')
9
10
11 class DescribedAs(BaseMatcher):
12
13 def __init__(self, description_template, matcher, *values):
14 self.template = description_template
15 self.matcher = matcher
16 self.values = values
17
18 def matches(self, item, mismatch_description=None):
19 return self.matcher.matches(item, mismatch_description)
20
21 def describe_mismatch(self, item, mismatch_description):
22 self.matcher.describe_mismatch(item, mismatch_description)
23
24 def describe_to(self, description):
25 text_start = 0
26 for match in re.finditer(ARG_PATTERN, self.template):
27 description.append_text(self.template[text_start:match.start()])
28 arg_index = int(match.group()[1:])
29 description.append_description_of(self.values[arg_index])
30 text_start = match.end()
31
32 if text_start < len(self.template):
33 description.append_text(self.template[text_start:])
34
35
36 def described_as(description, matcher, *values):
37 """Adds custom failure description to a given matcher.
38
39 :param description: Overrides the matcher's description.
40 :param matcher: The matcher to satisfy.
41 :param value1,...: Optional comma-separated list of substitution values.
42
43 The description may contain substitution placeholders %0, %1, etc. These
44 will be replaced by any values that follow the matcher.
45
46 """
47 return DescribedAs(description, matcher, *values)
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4 from hamcrest.core.base_matcher import BaseMatcher
5 from hamcrest.core.helpers.wrap_matcher import wrap_matcher, is_matchable_type
6 from isinstanceof import instance_of
7
8
9 class Is(BaseMatcher):
10
11 def __init__(self, matcher):
12 self.matcher = matcher
13
14 def matches(self, item, mismatch_description=None):
15 return self.matcher.matches(item, mismatch_description)
16
17 def describe_mismatch(self, item, mismatch_description):
18 return self.matcher.describe_mismatch(item, mismatch_description)
19
20 def describe_to(self, description):
21 description.append_description_of(self.matcher)
22
23
24 def wrap_value_or_type(x):
25 if is_matchable_type(x):
26 return instance_of(x)
27 else:
28 return wrap_matcher(x)
29
30
31 def is_(x):
32 """Decorates another matcher, or provides shortcuts to the frequently used
33 ``is(equal_to(x))`` and ``is(instance_of(x))``.
34
35 :param x: The matcher to satisfy, or a type for
36 :py:func:`~hamcrest.core.core.isinstanceof.instance_of` matching, or an
37 expected value for :py:func:`~hamcrest.core.core.isequal.equal_to`
38 matching.
39
40 This matcher compares the evaluated object to the given matcher.
41
42 .. note::
43
44 PyHamcrest's ``is_`` matcher is unrelated to Python's ``is`` operator.
45 The matcher for object identity is
46 :py:func:`~hamcrest.core.core.issame.same_instance`.
47
48 If the ``x`` argument is a matcher, its behavior is retained, but the test
49 may be more expressive. For example::
50
51 assert_that(value, less_than(5))
52 assert_that(value, is_(less_than(5)))
53
54 If the ``x`` argument is a type, it is wrapped in an
55 :py:func:`~hamcrest.core.core.isinstanceof.instance_of` matcher. This makes
56 the following statements equivalent::
57
58 assert_that(cheese, instance_of(Cheddar))
59 assert_that(cheese, is_(instance_of(Cheddar)))
60 assert_that(cheese, is_(Cheddar))
61
62 Otherwise, if the ``x`` argument is not a matcher, it is wrapped in an
63 :py:func:`~hamcrest.core.core.isequal.equal_to` matcher. This makes the
64 following statements equivalent::
65
66 assert_that(cheese, equal_to(smelly))
67 assert_that(cheese, is_(equal_to(smelly)))
68 assert_that(cheese, is_(smelly))
69
70 Choose the style that makes your expression most readable. This will vary
71 depending on context.
72
73 """
74 return Is(wrap_value_or_type(x))
0 from hamcrest.core.base_matcher import BaseMatcher
1
2 __author__ = "Jon Reid"
3 __copyright__ = "Copyright 2011 hamcrest.org"
4 __license__ = "BSD, see License.txt"
5
6
7 class IsAnything(BaseMatcher):
8
9 def __init__(self, description):
10 self.description = description
11 if not description:
12 self.description = 'ANYTHING'
13
14 def _matches(self, item):
15 return True
16
17 def describe_to(self, description):
18 description.append_text(self.description)
19
20
21 def anything(description=None):
22 """Matches anything.
23
24 :param description: Optional string used to describe this matcher.
25
26 This matcher always evaluates to ``True``. Specify this in composite
27 matchers when the value of a particular element is unimportant.
28
29 """
30 return IsAnything(description)
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4 from hamcrest.core.base_matcher import BaseMatcher
5 from hamcrest.core.matcher import Matcher
6
7
8 class IsEqual(BaseMatcher):
9
10 def __init__(self, equals):
11 self.object = equals
12
13 def _matches(self, item):
14 return item == self.object
15
16 def describe_to(self, description):
17 nested_matcher = isinstance(self.object, Matcher)
18 if nested_matcher:
19 description.append_text('<')
20 description.append_description_of(self.object)
21 if nested_matcher:
22 description.append_text('>')
23
24
25 def equal_to(obj):
26 """Matches if object is equal to a given object.
27
28 :param obj: The object to compare against as the expected value.
29
30 This matcher compares the evaluated object to ``obj`` for equality."""
31 return IsEqual(obj)
0 from hamcrest.core.base_matcher import BaseMatcher
1 from hamcrest.core.helpers.wrap_matcher import is_matchable_type
2
3 __author__ = "Jon Reid"
4 __copyright__ = "Copyright 2011 hamcrest.org"
5 __license__ = "BSD, see License.txt"
6
7 import types
8
9 class IsInstanceOf(BaseMatcher):
10
11 def __init__(self, expected_type):
12 if not is_matchable_type(expected_type):
13 raise TypeError('IsInstanceOf requires type')
14 self.expected_type = expected_type
15
16 def _matches(self, item):
17 return isinstance(item, self.expected_type)
18
19 def describe_to(self, description):
20 description.append_text('an instance of ') \
21 .append_text(self.expected_type.__name__)
22
23
24 def instance_of(atype):
25 """Matches if object is an instance of, or inherits from, a given type.
26
27 :param atype: The type to compare against as the expected type.
28
29 This matcher checks whether the evaluated object is an instance of
30 ``atype`` or an instance of any class that inherits from ``atype``.
31
32 Example::
33
34 instance_of(str)
35
36 """
37 return IsInstanceOf(atype)
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4 from hamcrest.core.base_matcher import BaseMatcher
5 from isnot import is_not
6
7
8 class IsNone(BaseMatcher):
9
10 def _matches(self, item):
11 return item is None
12
13 def describe_to(self, description):
14 description.append_text('None')
15
16
17 def none():
18 """Matches if object is ``None``."""
19 return IsNone()
20
21
22 def not_none():
23 """Matches if object is not ``None``."""
24 return is_not(none())
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4 from hamcrest.core.base_matcher import BaseMatcher, Matcher
5 from hamcrest.core.helpers.wrap_matcher import wrap_matcher, is_matchable_type
6 from isequal import equal_to
7 from isinstanceof import instance_of
8
9
10 class IsNot(BaseMatcher):
11
12 def __init__(self, matcher):
13 self.matcher = matcher
14
15 def _matches(self, item):
16 return not self.matcher.matches(item)
17
18 def describe_to(self, description):
19 description.append_text('not ').append_description_of(self.matcher)
20
21
22 def wrap_value_or_type(x):
23 if is_matchable_type(x):
24 return instance_of(x)
25 else:
26 return wrap_matcher(x)
27
28
29 def is_not(match):
30 """Inverts the given matcher to its logical negation.
31
32 :param match: The matcher to negate.
33
34 This matcher compares the evaluated object to the negation of the given
35 matcher. If the ``match`` argument is not a matcher, it is implicitly
36 wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to
37 check for equality, and thus matches for inequality.
38
39 Examples::
40
41 assert_that(cheese, is_not(equal_to(smelly)))
42 assert_that(cheese, is_not(smelly))
43
44 """
45 return IsNot(wrap_value_or_type(match))
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4 from hamcrest.core.base_matcher import BaseMatcher
5
6
7 class IsSame(BaseMatcher):
8
9 def __init__(self, object):
10 self.object = object
11
12 def _matches(self, item):
13 return item is self.object
14
15 def describe_to(self, description):
16 description.append_text('same instance as ') \
17 .append_text(hex(id(self.object))) \
18 .append_text(' ') \
19 .append_description_of(self.object)
20
21 def describe_mismatch(self, item, mismatch_description):
22 mismatch_description.append_text('was ')
23 if item is not None:
24 mismatch_description.append_text(hex(id(item))) \
25 .append_text(' ')
26 mismatch_description.append_description_of(item)
27
28
29 def same_instance(obj):
30 """Matches if evaluated object is the same instance as a given object.
31
32 :param obj: The object to compare against as the expected value.
33
34 This matcher invokes the ``is`` identity operator to determine if the
35 evaluated object is the the same object as ``obj``.
36
37 """
38 return IsSame(obj)
0 from weakref import ref
1 import re
2 import sys
3 from hamcrest.core.base_matcher import BaseMatcher
4 from hamcrest.core.helpers.wrap_matcher import wrap_matcher
5 from hamcrest.core.compat import is_callable
6
7 __author__ = "Per Fagrell"
8 __copyright__ = "Copyright 2013 hamcrest.org"
9 __license__ = "BSD, see License.txt"
10
11
12 class Raises(BaseMatcher):
13 def __init__(self, expected, pattern=None):
14 self.pattern = pattern
15 self.expected = expected
16 self.actual = None
17 self.function = None
18
19 def _matches(self, function):
20 if not is_callable(function):
21 return False
22
23 self.function = ref(function)
24 return self._call_function(function)
25
26 def _call_function(self, function):
27 self.actual = None
28 try:
29 function()
30 except Exception:
31 self.actual = sys.exc_info()[1]
32
33 if isinstance(self.actual, self.expected):
34 if self.pattern is not None:
35 return re.search(self.pattern, str(self.actual)) is not None
36 return True
37 return False
38
39 def describe_to(self, description):
40 description.append_text('Expected a callable raising %s' % self.expected)
41
42 def describe_mismatch(self, item, description):
43 if not is_callable(item):
44 description.append_text('%s is not callable' % item)
45 return
46
47 function = None if self.function is None else self.function()
48 if function is None or function is not item:
49 self.function = ref(item)
50 if not self._call_function(item):
51 return
52
53 if self.actual is None:
54 description.append_text('No exception raised.')
55 elif isinstance(self.actual, self.expected) and self.pattern is not None:
56 description.append_text('Correct assertion type raised, but the expected pattern ("%s") not found.' % self.pattern)
57 description.append_text('\n message was: "%s"' % str(self.actual))
58 else:
59 description.append_text('%s was raised instead' % type(self.actual))
60
61
62 def raises(exception, pattern=None):
63 """Matches if the called function raised the expected exception.
64
65 :param exception: The class of the expected exception
66 :param pattern: Optional regular expression to match exception message.
67
68 Expects the actual to be wrapped by using :py:func:`~hamcrest.core.core.raises.calling`,
69 or a callable taking no arguments.
70 Optional argument pattern should be a string containing a regular expression. If provided,
71 the string representation of the actual exception - e.g. `str(actual)` - must match pattern.
72
73 Examples::
74
75 assert_that(calling(int).with_args('q'), raises(TypeError))
76 assert_that(calling(parse, broken_input), raises(ValueError))
77 """
78 return Raises(exception, pattern)
79
80
81 class DeferredCallable(object):
82 def __init__(self, func):
83 self.func = func
84 self.args = tuple()
85 self.kwargs = {}
86
87 def __call__(self):
88 self.func(*self.args, **self.kwargs)
89
90 def with_args(self, *args, **kwargs):
91 self.args = args
92 self.kwargs = kwargs
93 return self
94
95
96 def calling(func):
97 """Wrapper for function call that delays the actual execution so that
98 :py:func:`~hamcrest.core.core.raises.raises` matcher can catch any thrown exception.
99
100 :param func: The function or method to be called
101
102 The arguments can be provided with a call to the `with_args` function on the returned
103 object::
104
105 calling(my_method).with_args(arguments, and_='keywords')
106 """
107 return DeferredCallable(func)
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4
5 class Description(object):
6 """A description of a :py:class:`~hamcrest.core.matcher.Matcher`.
7
8 A :py:class:`~hamcrest.core.matcher.Matcher` will describe itself to a
9 description which can later be used for reporting.
10
11 """
12
13 def append_text(self, text):
14 """Appends some plain text to the description.
15
16 :returns: ``self``, for chaining
17
18 """
19 raise NotImplementedError('append_text')
20
21 def append_description_of(self, value):
22 """Appends description of given value to this description.
23
24 If the value implements
25 :py:meth:`~hamcrest.core.selfdescribing.SelfDescribing.describe_to`,
26 then it will be used.
27
28 :returns: ``self``, for chaining
29
30 """
31 raise NotImplementedError('append_description_of')
32
33 def append_value(self, value):
34 """Appends an arbitary value to the description.
35
36 **Deprecated:** Call
37 :py:meth:`~hamcrest.core.description.Description.append_description_of`
38 instead.
39
40 :returns: ``self``, for chaining
41
42 """
43 raise NotImplementedError('append_value')
44
45 def append_list(self, start, separator, end, list):
46 """Appends a list of objects to the description.
47
48 :param start: String that will begin the list description.
49 :param separator: String that will separate each object in the
50 description.
51 :param end: String that will end the list description.
52 :param list: List of objects to be described.
53
54 :returns: ``self``, for chaining
55
56 """
57 raise NotImplementedError('append_list')
0 """Utilities for writing Matchers."""
1
2 __author__ = "Jon Reid"
3 __copyright__ = "Copyright 2011 hamcrest.org"
4 __license__ = "BSD, see License.txt"
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4
5 def hasmethod(obj, methodname):
6 """Does ``obj`` have a method named ``methodname``?"""
7
8 if not hasattr(obj, methodname):
9 return False
10 method = getattr(obj, methodname)
11 return callable(method)
0 from hamcrest.core.base_matcher import Matcher
1 from hamcrest.core.core.isequal import equal_to
2
3 __author__ = "Jon Reid"
4 __copyright__ = "Copyright 2011 hamcrest.org"
5 __license__ = "BSD, see License.txt"
6
7 import types
8
9 def wrap_matcher(x):
10 """Wraps argument in a matcher, if necessary.
11
12 :returns: the argument as-is if it is already a matcher, otherwise wrapped
13 in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher.
14
15 """
16 if isinstance(x, Matcher):
17 return x
18 else:
19 return equal_to(x)
20
21 def is_matchable_type(expected_type):
22 if isinstance(expected_type, type):
23 return True
24
25 if type(expected_type) == types.ClassType:
26 return True
27
28 return False
0 from selfdescribing import SelfDescribing
1
2 __author__ = "Jon Reid"
3 __copyright__ = "Copyright 2011 hamcrest.org"
4 __license__ = "BSD, see License.txt"
5
6
7 class Matcher(SelfDescribing):
8 """A matcher over acceptable values.
9
10 A matcher is able to describe itself to give feedback when it fails.
11
12 Matcher implementations should *not* directly implement this protocol.
13 Instead, *extend* the :py:class:`~hamcrest.core.base_matcher.BaseMatcher`
14 class, which will ensure that the
15 :py:class:`~hamcrest.core.matcher.Matcher` API can grow to support new
16 features and remain compatible with all
17 :py:class:`~hamcrest.core.matcher.Matcher` implementations.
18
19 """
20
21 def matches(self, item, mismatch_description=None):
22 """Evaluates the matcher for argument item.
23
24 If a mismatch is detected and argument ``mismatch_description`` is
25 provided, it will generate a description of why the matcher has not
26 accepted the item.
27
28 :param item: The object against which the matcher is evaluated.
29 :returns: ``True`` if ``item`` matches, otherwise ``False``.
30
31 """
32 raise NotImplementedError('matches')
33
34 def describe_mismatch(self, item, mismatch_description):
35 """Generates a description of why the matcher has not accepted the
36 item.
37
38 The description will be part of a larger description of why a matching
39 failed, so it should be concise.
40
41 This method assumes that ``matches(item)`` is ``False``, but will not
42 check this.
43
44 :param item: The item that the
45 :py:class:`~hamcrest.core.matcher.Matcher` has rejected.
46 :param mismatch_description: The description to be built or appended
47 to.
48
49 """
50 raise NotImplementedError('describe_mismatch')
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4
5 class SelfDescribing(object):
6 """The ability of an object to describe itself."""
7
8 def describe_to(self, description):
9 """Generates a description of the object.
10
11 The description may be part of a description of a larger object of
12 which this is just a component, so it should be worded appropriately.
13
14 :param description: The description to be built or appended to.
15
16 """
17 raise NotImplementedError('describe_to')
0 from hamcrest.core.selfdescribing import SelfDescribing
1
2 import warnings
3
4 __author__ = "Jon Reid"
5 __copyright__ = "Copyright 2011 hamcrest.org"
6 __license__ = "BSD, see License.txt"
7
8
9 class SelfDescribingValue(SelfDescribing):
10 """Wrap any value in a ``SelfDescribingValue`` to satisfy the
11 :py:class:`~hamcrest.core.selfdescribing.SelfDescribing` interface.
12
13 **Deprecated:** No need for this class now that
14 :py:meth:`~hamcrest.core.description.Description.append_description_of`
15 handles any type of value.
16
17 """
18
19 def __init__(self, value):
20 warnings.warn('SelfDescribingValue no longer needed',
21 DeprecationWarning)
22 self.value = value
23
24 def describe_to(self, description):
25 """Generates a description of the value."""
26 description.append_value(self.value)
0 from base_description import BaseDescription
1
2 __author__ = "Jon Reid"
3 __copyright__ = "Copyright 2011 hamcrest.org"
4 __license__ = "BSD, see License.txt"
5
6
7 def tostring(selfdescribing):
8 """Returns the description of a
9 :py:class:`~hamcrest.core.selfdescribing.SelfDescribing` object as a
10 string.
11
12 :param selfdescribing: The object to be described.
13 :returns: The description of the object.
14 """
15 return str(StringDescription().append_description_of(selfdescribing))
16
17
18 class StringDescription(BaseDescription):
19 """A :py:class:`~hamcrest.core.description.Description` that is stored as a
20 string.
21
22 """
23
24 def __init__(self):
25 self.out = ''
26
27 def __str__(self):
28 """Returns the description."""
29 return self.out
30
31 def append(self, string):
32 self.out += string
0 """Library of Matcher implementations."""
1
2 from hamcrest.core import *
3 from collection import *
4 from integration import *
5 from number import *
6 from object import *
7 from text import *
8
9 __author__ = "Jon Reid"
10 __copyright__ = "Copyright 2011 hamcrest.org"
11 __license__ = "BSD, see License.txt"
12
13 __all__ = [
14 'has_entry',
15 'has_entries',
16 'has_key',
17 'has_value',
18 'is_in',
19 'empty',
20 'has_item',
21 'has_items',
22 'contains_inanyorder',
23 'contains',
24 'only_contains',
25 'match_equality',
26 'matches_regexp',
27 'close_to',
28 'greater_than',
29 'greater_than_or_equal_to',
30 'less_than',
31 'less_than_or_equal_to',
32 'has_length',
33 'has_property',
34 'has_properties',
35 'has_string',
36 'equal_to_ignoring_case',
37 'equal_to_ignoring_whitespace',
38 'contains_string',
39 'ends_with',
40 'starts_with',
41 'string_contains_in_order',
42 ]
0 """Matchers of collections."""
1 from __future__ import absolute_import
2 from .isdict_containing import has_entry
3 from .isdict_containingentries import has_entries
4 from .isdict_containingkey import has_key
5 from .isdict_containingvalue import has_value
6 from .isin import is_in
7 from .issequence_containing import has_item, has_items
8 from .issequence_containinginanyorder import contains_inanyorder
9 from .issequence_containinginorder import contains
10 from .issequence_onlycontaining import only_contains
11 from .is_empty import empty
12
13 __author__ = "Chris Rose"
14 __copyright__ = "Copyright 2013 hamcrest.org"
15 __license__ = "BSD, see License.txt"
0 from hamcrest.core.base_matcher import BaseMatcher
1
2 __author__ = "Chris Rose"
3 __copyright__ = "Copyright 2012 hamcrest.org"
4 __license__ = "BSD, see License.txt"
5
6
7 class IsEmpty(BaseMatcher):
8
9 def matches(self, item, mismatch_description=None):
10 try:
11 if len(item) == 0:
12 return True
13
14 if mismatch_description:
15 mismatch_description \
16 .append_text('has %d item(s)' % len(item))
17
18 except TypeError:
19 if mismatch_description:
20 mismatch_description \
21 .append_text('does not support length')
22
23 return False
24
25 def describe_to(self, description):
26 description.append_text('an empty collection')
27
28
29 def empty():
30 """
31 This matcher matches any collection-like object that responds to the
32 __len__ method, and has a length of 0.
33 """
34 return IsEmpty()
0 from hamcrest.core.base_matcher import BaseMatcher
1 from hamcrest.core.helpers.hasmethod import hasmethod
2 from hamcrest.core.helpers.wrap_matcher import wrap_matcher
3
4 __author__ = "Jon Reid"
5 __copyright__ = "Copyright 2011 hamcrest.org"
6 __license__ = "BSD, see License.txt"
7
8
9 class IsDictContaining(BaseMatcher):
10
11 def __init__(self, key_matcher, value_matcher):
12 self.key_matcher = key_matcher
13 self.value_matcher = value_matcher
14
15 def _matches(self, dictionary):
16 if hasmethod(dictionary, 'items'):
17 for key, value in dictionary.items():
18 if self.key_matcher.matches(key) and self.value_matcher.matches(value):
19 return True
20 return False
21
22 def describe_to(self, description):
23 description.append_text('a dictionary containing [') \
24 .append_description_of(self.key_matcher) \
25 .append_text(': ') \
26 .append_description_of(self.value_matcher) \
27 .append_text(']')
28
29
30 def has_entry(key_match, value_match):
31 """Matches if dictionary contains key-value entry satisfying a given pair
32 of matchers.
33
34 :param key_match: The matcher to satisfy for the key, or an expected value
35 for :py:func:`~hamcrest.core.core.isequal.equal_to` matching.
36 :param value_match: The matcher to satisfy for the value, or an expected
37 value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching.
38
39 This matcher iterates the evaluated dictionary, searching for any key-value
40 entry that satisfies ``key_match`` and ``value_match``. If a matching entry
41 is found, ``has_entry`` is satisfied.
42
43 Any argument that is not a matcher is implicitly wrapped in an
44 :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
45 equality.
46
47 Examples::
48
49 has_entry(equal_to('foo'), equal_to(1))
50 has_entry('foo', 1)
51
52 """
53 return IsDictContaining(wrap_matcher(key_match), wrap_matcher(value_match))
0 from hamcrest.core.base_matcher import BaseMatcher
1 from hamcrest.core.helpers.hasmethod import hasmethod
2 from hamcrest.core.helpers.wrap_matcher import wrap_matcher
3
4 __author__ = "Jon Reid"
5 __copyright__ = "Copyright 2011 hamcrest.org"
6 __license__ = "BSD, see License.txt"
7
8
9 class IsDictContainingEntries(BaseMatcher):
10
11 def __init__(self, value_matchers):
12 self.value_matchers = value_matchers
13
14 def _not_a_dictionary(self, dictionary, mismatch_description):
15 if mismatch_description:
16 mismatch_description.append_description_of(dictionary) \
17 .append_text(' is not a mapping object')
18 return False
19
20 def matches(self, dictionary, mismatch_description=None):
21 for key in self.value_matchers:
22
23 try:
24 if not key in dictionary:
25 if mismatch_description:
26 mismatch_description.append_text('no ') \
27 .append_description_of(key) \
28 .append_text(' key in ') \
29 .append_description_of(dictionary)
30 return False
31 except TypeError:
32 return self._not_a_dictionary(dictionary, mismatch_description)
33
34 value_matcher = self.value_matchers[key]
35 try:
36 actual_value = dictionary[key]
37 except TypeError:
38 return self._not_a_dictionary(dictionary, mismatch_description)
39
40 if not value_matcher.matches(actual_value):
41 if mismatch_description:
42 mismatch_description.append_text('value for ') \
43 .append_description_of(key) \
44 .append_text(' ')
45 value_matcher.describe_mismatch(actual_value, mismatch_description)
46 return False
47
48 return True
49
50 def describe_mismatch(self, item, mismatch_description):
51 self.matches(item, mismatch_description)
52
53 def describe_keyvalue(self, index, description):
54 """Describes key-value pair at given index."""
55 description.append_description_of(index) \
56 .append_text(': ') \
57 .append_description_of(self.value_matchers[index])
58
59 def describe_to(self, description):
60 description.append_text('a dictionary containing {')
61 first = True
62 for key in self.value_matchers:
63 if not first:
64 description.append_text(', ')
65 self.describe_keyvalue(key, description)
66 first = False
67 description.append_text('}')
68
69
70 def has_entries(*keys_valuematchers, **kv_args):
71 """Matches if dictionary contains entries satisfying a dictionary of keys
72 and corresponding value matchers.
73
74 :param matcher_dict: A dictionary mapping keys to associated value matchers,
75 or to expected values for
76 :py:func:`~hamcrest.core.core.isequal.equal_to` matching.
77
78 Note that the keys must be actual keys, not matchers. Any value argument
79 that is not a matcher is implicitly wrapped in an
80 :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
81 equality.
82
83 Examples::
84
85 has_entries({'foo':equal_to(1), 'bar':equal_to(2)})
86 has_entries({'foo':1, 'bar':2})
87
88 ``has_entries`` also accepts a list of keyword arguments:
89
90 .. function:: has_entries(keyword1=value_matcher1[, keyword2=value_matcher2[, ...]])
91
92 :param keyword1: A keyword to look up.
93 :param valueMatcher1: The matcher to satisfy for the value, or an expected
94 value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching.
95
96 Examples::
97
98 has_entries(foo=equal_to(1), bar=equal_to(2))
99 has_entries(foo=1, bar=2)
100
101 Finally, ``has_entries`` also accepts a list of alternating keys and their
102 value matchers:
103
104 .. function:: has_entries(key1, value_matcher1[, ...])
105
106 :param key1: A key (not a matcher) to look up.
107 :param valueMatcher1: The matcher to satisfy for the value, or an expected
108 value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching.
109
110 Examples::
111
112 has_entries('foo', equal_to(1), 'bar', equal_to(2))
113 has_entries('foo', 1, 'bar', 2)
114
115 """
116 if len(keys_valuematchers) == 1:
117 try:
118 base_dict = keys_valuematchers[0].copy()
119 for key in base_dict:
120 base_dict[key] = wrap_matcher(base_dict[key])
121 except AttributeError:
122 raise ValueError('single-argument calls to has_entries must pass a dict as the argument')
123 else:
124 if len(keys_valuematchers) % 2:
125 raise ValueError('has_entries requires key-value pairs')
126 base_dict = {}
127 for index in range(int(len(keys_valuematchers) / 2)):
128 base_dict[keys_valuematchers[2 * index]] = wrap_matcher(keys_valuematchers[2 * index + 1])
129
130 for key, value in kv_args.items():
131 base_dict[key] = wrap_matcher(value)
132
133 return IsDictContainingEntries(base_dict)
0 from hamcrest.core.base_matcher import BaseMatcher
1 from hamcrest.core.helpers.hasmethod import hasmethod
2 from hamcrest.core.helpers.wrap_matcher import wrap_matcher
3
4 __author__ = "Jon Reid"
5 __copyright__ = "Copyright 2011 hamcrest.org"
6 __license__ = "BSD, see License.txt"
7
8
9 class IsDictContainingKey(BaseMatcher):
10
11 def __init__(self, key_matcher):
12 self.key_matcher = key_matcher
13
14 def _matches(self, dictionary):
15 if hasmethod(dictionary, 'keys'):
16 for key in dictionary.keys():
17 if self.key_matcher.matches(key):
18 return True
19 return False
20
21 def describe_to(self, description):
22 description.append_text('a dictionary containing key ') \
23 .append_description_of(self.key_matcher)
24
25
26 def has_key(key_match):
27 """Matches if dictionary contains an entry whose key satisfies a given
28 matcher.
29
30 :param key_match: The matcher to satisfy for the key, or an expected value
31 for :py:func:`~hamcrest.core.core.isequal.equal_to` matching.
32
33 This matcher iterates the evaluated dictionary, searching for any key-value
34 entry whose key satisfies the given matcher. If a matching entry is found,
35 ``has_key`` is satisfied.
36
37 Any argument that is not a matcher is implicitly wrapped in an
38 :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
39 equality.
40
41 Examples::
42
43 has_key(equal_to('foo'))
44 has_key('foo')
45
46 """
47 return IsDictContainingKey(wrap_matcher(key_match))
0 from hamcrest.core.base_matcher import BaseMatcher
1 from hamcrest.core.helpers.hasmethod import hasmethod
2 from hamcrest.core.helpers.wrap_matcher import wrap_matcher
3
4 __author__ = "Jon Reid"
5 __copyright__ = "Copyright 2011 hamcrest.org"
6 __license__ = "BSD, see License.txt"
7
8
9 class IsDictContainingValue(BaseMatcher):
10
11 def __init__(self, value_matcher):
12 self.value_matcher = value_matcher
13
14 def _matches(self, dictionary):
15 if hasmethod(dictionary, 'values'):
16 for value in dictionary.values():
17 if self.value_matcher.matches(value):
18 return True
19 return False
20
21 def describe_to(self, description):
22 description.append_text('a dictionary containing value ') \
23 .append_description_of(self.value_matcher)
24
25
26 def has_value(value):
27 """Matches if dictionary contains an entry whose value satisfies a given
28 matcher.
29
30 :param value_match: The matcher to satisfy for the value, or an expected
31 value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching.
32
33 This matcher iterates the evaluated dictionary, searching for any key-value
34 entry whose value satisfies the given matcher. If a matching entry is
35 found, ``has_value`` is satisfied.
36
37 Any argument that is not a matcher is implicitly wrapped in an
38 :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
39 equality.
40
41 Examples::
42
43 has_value(equal_to('bar'))
44 has_value('bar')
45
46 """
47 return IsDictContainingValue(wrap_matcher(value))
0 from hamcrest.core.base_matcher import BaseMatcher
1
2 __author__ = "Jon Reid"
3 __copyright__ = "Copyright 2011 hamcrest.org"
4 __license__ = "BSD, see License.txt"
5
6
7 class IsIn(BaseMatcher):
8
9 def __init__(self, sequence):
10 self.sequence = sequence
11
12 def _matches(self, item):
13 return item in self.sequence
14
15 def describe_to(self, description):
16 description.append_text('one of ') \
17 .append_list('(', ', ', ')', self.sequence)
18
19
20 def is_in(sequence):
21 """Matches if evaluated object is present in a given sequence.
22
23 :param sequence: The sequence to search.
24
25 This matcher invokes the ``in`` membership operator to determine if the
26 evaluated object is a member of the sequence.
27
28 """
29 return IsIn(sequence)
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4 from hamcrest.core.base_matcher import BaseMatcher
5 from hamcrest.core.core.allof import all_of
6 from hamcrest.core.helpers.hasmethod import hasmethod
7 from hamcrest.core.helpers.wrap_matcher import wrap_matcher
8
9
10 class IsSequenceContaining(BaseMatcher):
11
12 def __init__(self, element_matcher):
13 self.element_matcher = element_matcher
14
15 def _matches(self, sequence):
16 try:
17 for item in sequence:
18 if self.element_matcher.matches(item):
19 return True
20 except TypeError: # not a sequence
21 return False
22
23 def describe_to(self, description):
24 description.append_text('a sequence containing ') \
25 .append_description_of(self.element_matcher)
26
27
28 # It'd be great to make use of all_of, but we can't be sure we won't
29 # be seeing a one-time sequence here (like a generator); see issue #20
30 # Instead, we wrap it inside a class that will convert the sequence into
31 # a concrete list and then hand it off to the all_of matcher.
32 class IsSequenceContainingEvery(BaseMatcher):
33
34 def __init__(self, *element_matchers):
35 delegates = [has_item(e) for e in element_matchers]
36 self.matcher = all_of(*delegates)
37
38 def _matches(self, sequence):
39 try:
40 return self.matcher.matches(list(sequence))
41 except TypeError:
42 return False
43
44 def describe_mismatch(self, item, mismatch_description):
45 self.matcher.describe_mismatch(item, mismatch_description)
46
47 def describe_to(self, description):
48 self.matcher.describe_to(description)
49
50
51
52 def has_item(match):
53 """Matches if any element of sequence satisfies a given matcher.
54
55 :param match: The matcher to satisfy, or an expected value for
56 :py:func:`~hamcrest.core.core.isequal.equal_to` matching.
57
58 This matcher iterates the evaluated sequence, searching for any element
59 that satisfies a given matcher. If a matching element is found,
60 ``has_item`` is satisfied.
61
62 If the ``match`` argument is not a matcher, it is implicitly wrapped in an
63 :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
64 equality.
65
66 """
67 return IsSequenceContaining(wrap_matcher(match))
68
69
70 def has_items(*items):
71 """Matches if all of the given matchers are satisfied by any elements of
72 the sequence.
73
74 :param match1,...: A comma-separated list of matchers.
75
76 This matcher iterates the given matchers, searching for any elements in the
77 evaluated sequence that satisfy them. If each matcher is satisfied, then
78 ``has_items`` is satisfied.
79
80 Any argument that is not a matcher is implicitly wrapped in an
81 :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
82 equality.
83
84 """
85 matchers = []
86 for item in items:
87 matchers.append(wrap_matcher(item))
88 return IsSequenceContainingEvery(*matchers)
0 from hamcrest.core.base_matcher import BaseMatcher
1 from hamcrest.core.helpers.hasmethod import hasmethod
2 from hamcrest.core.helpers.wrap_matcher import wrap_matcher
3
4 __author__ = "Jon Reid"
5 __copyright__ = "Copyright 2011 hamcrest.org"
6 __license__ = "BSD, see License.txt"
7
8
9 class MatchInAnyOrder(object):
10 def __init__(self, matchers, mismatch_description):
11 self.matchers = matchers[:]
12 self.mismatch_description = mismatch_description
13
14 def matches(self, item):
15 return self.isnotsurplus(item) and self.ismatched(item)
16
17 def isfinished(self, sequence):
18 if not self.matchers:
19 return True
20 if self.mismatch_description:
21 self.mismatch_description.append_text('no item matches: ') \
22 .append_list('', ', ', '', self.matchers) \
23 .append_text(' in ') \
24 .append_list('[', ', ', ']', sequence)
25 return False
26
27 def isnotsurplus(self, item):
28 if not self.matchers:
29 if self.mismatch_description:
30 self.mismatch_description.append_text('not matched: ') \
31 .append_description_of(item)
32 return False
33 return True
34
35 def ismatched(self, item):
36 for index, matcher in enumerate(self.matchers):
37 if matcher.matches(item):
38 del self.matchers[index]
39 return True
40
41 if self.mismatch_description:
42 self.mismatch_description.append_text('not matched: ') \
43 .append_description_of(item)
44 return False
45
46
47 class IsSequenceContainingInAnyOrder(BaseMatcher):
48
49 def __init__(self, matchers):
50 self.matchers = matchers
51
52 def matches(self, sequence, mismatch_description=None):
53 try:
54 sequence = list(sequence)
55 matchsequence = MatchInAnyOrder(self.matchers, mismatch_description)
56 for item in sequence:
57 if not matchsequence.matches(item):
58 return False
59 return matchsequence.isfinished(sequence)
60 except TypeError:
61 if mismatch_description:
62 super(IsSequenceContainingInAnyOrder, self) \
63 .describe_mismatch(sequence, mismatch_description)
64 return False
65
66 def describe_mismatch(self, item, mismatch_description):
67 self.matches(item, mismatch_description)
68
69 def describe_to(self, description):
70 description.append_text('a sequence over ') \
71 .append_list('[', ', ', ']', self.matchers) \
72 .append_text(' in any order')
73
74
75 def contains_inanyorder(*items):
76 """Matches if sequences's elements, in any order, satisfy a given list of
77 matchers.
78
79 :param match1,...: A comma-separated list of matchers.
80
81 This matcher iterates the evaluated sequence, seeing if each element
82 satisfies any of the given matchers. The matchers are tried from left to
83 right, and when a satisfied matcher is found, it is no longer a candidate
84 for the remaining elements. If a one-to-one correspondence is established
85 between elements and matchers, ``contains_inanyorder`` is satisfied.
86
87 Any argument that is not a matcher is implicitly wrapped in an
88 :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
89 equality.
90
91 """
92
93 matchers = []
94 for item in items:
95 matchers.append(wrap_matcher(item))
96 return IsSequenceContainingInAnyOrder(matchers)
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4 from hamcrest.core.base_matcher import BaseMatcher
5 from hamcrest.core.helpers.hasmethod import hasmethod
6 from hamcrest.core.helpers.wrap_matcher import wrap_matcher
7
8
9 class MatchingInOrder(object):
10 def __init__(self, matchers, mismatch_description):
11 self.matchers = matchers
12 self.mismatch_description = mismatch_description
13 self.next_match_index = 0
14
15 def matches(self, item):
16 return self.isnotsurplus(item) and self.ismatched(item)
17
18 def isfinished(self):
19 if self.next_match_index < len(self.matchers):
20 if self.mismatch_description:
21 self.mismatch_description.append_text('No item matched: ') \
22 .append_description_of(self.matchers[self.next_match_index])
23 return False
24 return True
25
26 def ismatched(self, item):
27 matcher = self.matchers[self.next_match_index]
28 if not matcher.matches(item):
29 if self.mismatch_description:
30 self.mismatch_description.append_text('item ' + str(self.next_match_index) + ': ')
31 matcher.describe_mismatch(item, self.mismatch_description)
32 return False
33 self.next_match_index += 1
34 return True
35
36 def isnotsurplus(self, item):
37 if len(self.matchers) <= self.next_match_index:
38 if self.mismatch_description:
39 self.mismatch_description.append_text('Not matched: ') \
40 .append_description_of(item)
41 return False
42 return True
43
44
45 class IsSequenceContainingInOrder(BaseMatcher):
46
47 def __init__(self, matchers):
48 self.matchers = matchers
49
50 def matches(self, sequence, mismatch_description=None):
51 try:
52 matchsequence = MatchingInOrder(self.matchers, mismatch_description)
53 for item in sequence:
54 if not matchsequence.matches(item):
55 return False
56 return matchsequence.isfinished()
57 except TypeError:
58 if mismatch_description:
59 super(IsSequenceContainingInOrder, self) \
60 .describe_mismatch(sequence, mismatch_description)
61 return False
62
63 def describe_mismatch(self, item, mismatch_description):
64 self.matches(item, mismatch_description)
65
66 def describe_to(self, description):
67 description.append_text('a sequence containing ') \
68 .append_list('[', ', ', ']', self.matchers)
69
70
71 def contains(*items):
72 """Matches if sequence's elements satisfy a given list of matchers, in order.
73
74 :param match1,...: A comma-separated list of matchers.
75
76 This matcher iterates the evaluated sequence and a given list of matchers,
77 seeing if each element satisfies its corresponding matcher.
78
79 Any argument that is not a matcher is implicitly wrapped in an
80 :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
81 equality.
82
83 """
84 matchers = []
85 for item in items:
86 matchers.append(wrap_matcher(item))
87 return IsSequenceContainingInOrder(matchers)
0 from hamcrest.core.base_matcher import BaseMatcher
1 from hamcrest.core.core.anyof import any_of
2 from hamcrest.core.helpers.hasmethod import hasmethod
3 from hamcrest.core.helpers.wrap_matcher import wrap_matcher
4
5 __author__ = "Jon Reid"
6 __copyright__ = "Copyright 2011 hamcrest.org"
7 __license__ = "BSD, see License.txt"
8
9
10 class IsSequenceOnlyContaining(BaseMatcher):
11
12 def __init__(self, matcher):
13 self.matcher = matcher
14
15 def _matches(self, sequence):
16 try:
17 sequence = list(sequence)
18 if len(sequence) == 0:
19 return False
20 for item in sequence:
21 if not self.matcher.matches(item):
22 return False
23 return True
24 except TypeError:
25 return False
26
27 def describe_to(self, description):
28 description.append_text('a sequence containing items matching ') \
29 .append_description_of(self.matcher)
30
31
32 def only_contains(*items):
33 """Matches if each element of sequence satisfies any of the given matchers.
34
35 :param match1,...: A comma-separated list of matchers.
36
37 This matcher iterates the evaluated sequence, confirming whether each
38 element satisfies any of the given matchers.
39
40 Example::
41
42 only_contains(less_than(4))
43
44 will match ``[3,1,2]``.
45
46 Any argument that is not a matcher is implicitly wrapped in an
47 :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
48 equality.
49
50 """
51 matchers = []
52 for item in items:
53 matchers.append(wrap_matcher(item))
54 return IsSequenceOnlyContaining(apply(any_of, matchers))
0 """Utilities for integrating Hamcrest with other libraries."""
1
2 from match_equality import match_equality
3
4 __author__ = "Jon Reid"
5 __copyright__ = "Copyright 2011 hamcrest.org"
6 __license__ = "BSD, see License.txt"
0 from hamcrest.core.string_description import tostring
1 from hamcrest.core.helpers.wrap_matcher import wrap_matcher
2
3 __author__ = "Chris Rose"
4 __copyright__ = "Copyright 2011 hamcrest.org"
5 __license__ = "BSD, see License.txt"
6 __unittest = True
7
8
9 class EqualityWrapper(object):
10
11 def __init__(self, matcher):
12 self.matcher = matcher
13
14 def __eq__(self, object):
15 return self.matcher.matches(object)
16
17 def __str__(self):
18 return repr(self)
19
20 def __repr__(self):
21 return tostring(self.matcher)
22
23
24 def match_equality(matcher):
25 """Wraps a matcher to define equality in terms of satisfying the matcher.
26
27 ``match_equality`` allows Hamcrest matchers to be used in libraries that
28 are not Hamcrest-aware. They might use the equality operator::
29
30 assert match_equality(matcher) == object
31
32 Or they might provide a method that uses equality for its test::
33
34 library.method_that_tests_eq(match_equality(matcher))
35
36 One concrete example is integrating with the ``assert_called_with`` methods
37 in Michael Foord's `mock <http://www.voidspace.org.uk/python/mock/>`_
38 library.
39
40 """
41 return EqualityWrapper(wrap_matcher(matcher))
0 """Matchers that perform numeric comparisons."""
1
2 from iscloseto import close_to
3 from ordering_comparison import greater_than, greater_than_or_equal_to, less_than, less_than_or_equal_to
4
5 __author__ = "Jon Reid"
6 __copyright__ = "Copyright 2011 hamcrest.org"
7 __license__ = "BSD, see License.txt"
0 from hamcrest.core.base_matcher import BaseMatcher
1 from math import fabs
2
3 __author__ = "Jon Reid"
4 __copyright__ = "Copyright 2011 hamcrest.org"
5 __license__ = "BSD, see License.txt"
6
7
8 def isnumeric(value):
9 """Confirm that 'value' can be treated numerically; duck-test accordingly
10 """
11 if isinstance(value, (int, float, complex, long)):
12 return True
13
14 try:
15 _ = (fabs(value) + 0 - 0) * 1
16 return True
17 except ArithmeticError:
18 return True
19 except:
20 return False
21 return False
22
23
24 class IsCloseTo(BaseMatcher):
25
26 def __init__(self, value, delta):
27 if not isnumeric(value):
28 raise TypeError('IsCloseTo value must be numeric')
29 if not isnumeric(delta):
30 raise TypeError('IsCloseTo delta must be numeric')
31
32 self.value = value
33 self.delta = delta
34
35 def _matches(self, item):
36 if not isnumeric(item):
37 return False
38 return fabs(item - self.value) <= self.delta
39
40 def describe_mismatch(self, item, mismatch_description):
41 if not isnumeric(item):
42 super(IsCloseTo, self).describe_mismatch(item, mismatch_description)
43 else:
44 actual_delta = fabs(item - self.value)
45 mismatch_description.append_description_of(item) \
46 .append_text(' differed by ') \
47 .append_description_of(actual_delta)
48
49 def describe_to(self, description):
50 description.append_text('a numeric value within ') \
51 .append_description_of(self.delta) \
52 .append_text(' of ') \
53 .append_description_of(self.value)
54
55
56 def close_to(value, delta):
57 """Matches if object is a number close to a given value, within a given
58 delta.
59
60 :param value: The value to compare against as the expected value.
61 :param delta: The maximum delta between the values for which the numbers
62 are considered close.
63
64 This matcher compares the evaluated object against ``value`` to see if the
65 difference is within a positive ``delta``.
66
67 Example::
68
69 close_to(3.0, 0.25)
70
71 """
72 return IsCloseTo(value, delta)
0 from hamcrest.core.base_matcher import BaseMatcher
1 import operator
2
3 __author__ = "Jon Reid"
4 __copyright__ = "Copyright 2011 hamcrest.org"
5 __license__ = "BSD, see License.txt"
6
7
8 class OrderingComparison(BaseMatcher):
9
10 def __init__(self, value, comparison_function, comparison_description):
11 self.value = value
12 self.comparison_function = comparison_function
13 self.comparison_description = comparison_description
14
15 def _matches(self, item):
16 return self.comparison_function(item, self.value)
17
18 def describe_to(self, description):
19 description.append_text('a value ') \
20 .append_text(self.comparison_description) \
21 .append_text(' ') \
22 .append_description_of(self.value)
23
24
25 def greater_than(value):
26 """Matches if object is greater than a given value.
27
28 :param value: The value to compare against.
29
30 """
31 return OrderingComparison(value, operator.gt, 'greater than')
32
33
34 def greater_than_or_equal_to(value):
35 """Matches if object is greater than or equal to a given value.
36
37 :param value: The value to compare against.
38
39 """
40 return OrderingComparison(value, operator.ge, 'greater than or equal to')
41
42
43 def less_than(value):
44 """Matches if object is less than a given value.
45
46 :param value: The value to compare against.
47
48 """
49 return OrderingComparison(value, operator.lt, 'less than')
50
51
52 def less_than_or_equal_to(value):
53 """Matches if object is less than or equal to a given value.
54
55 :param value: The value to compare against.
56
57 """
58 return OrderingComparison(value, operator.le, 'less than or equal to')
0 """Matchers that inspect objects and classes."""
1
2 from haslength import has_length
3 from hasproperty import has_property, has_properties
4 from hasstring import has_string
5
6 __author__ = "Jon Reid"
7 __copyright__ = "Copyright 2011 hamcrest.org"
8 __license__ = "BSD, see License.txt"
0 from hamcrest.core.base_matcher import BaseMatcher
1 from hamcrest.core.helpers.hasmethod import hasmethod
2 from hamcrest.core.helpers.wrap_matcher import wrap_matcher
3
4 __author__ = "Jon Reid"
5 __copyright__ = "Copyright 2011 hamcrest.org"
6 __license__ = "BSD, see License.txt"
7
8
9 class HasLength(BaseMatcher):
10
11 def __init__(self, len_matcher):
12 self.len_matcher = len_matcher
13
14 def _matches(self, item):
15 if not hasmethod(item, '__len__'):
16 return False
17 return self.len_matcher.matches(len(item))
18
19 def describe_mismatch(self, item, mismatch_description):
20 super(HasLength, self).describe_mismatch(item, mismatch_description)
21 if hasmethod(item, '__len__'):
22 mismatch_description.append_text(' with length of ') \
23 .append_description_of(len(item))
24
25 def describe_to(self, description):
26 description.append_text('an object with length of ') \
27 .append_description_of(self.len_matcher)
28
29
30 def has_length(match):
31 """Matches if ``len(item)`` satisfies a given matcher.
32
33 :param match: The matcher to satisfy, or an expected value for
34 :py:func:`~hamcrest.core.core.isequal.equal_to` matching.
35
36 This matcher invokes the :py:func:`len` function on the evaluated object to
37 get its length, passing the result to a given matcher for evaluation.
38
39 If the ``match`` argument is not a matcher, it is implicitly wrapped in an
40 :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
41 :equality.
42
43 Examples::
44
45 has_length(greater_than(6))
46 has_length(5)
47
48 """
49 return HasLength(wrap_matcher(match))
0 from hamcrest.core.base_matcher import BaseMatcher
1 from hamcrest.core import anything
2 from hamcrest.core.core.allof import all_of
3 from hamcrest.core.string_description import StringDescription
4 from hamcrest.core.helpers.hasmethod import hasmethod
5 from hamcrest.core.helpers.wrap_matcher import wrap_matcher as wrap_shortcut
6
7 __author__ = "Chris Rose"
8 __copyright__ = "Copyright 2011 hamcrest.org"
9 __license__ = "BSD, see License.txt"
10
11
12 class IsObjectWithProperty(BaseMatcher):
13
14 def __init__(self, property_name, value_matcher):
15 self.property_name = property_name
16 self.value_matcher = value_matcher
17
18 def _matches(self, o):
19 if o is None:
20 return False
21
22 if not hasattr(o, self.property_name):
23 return False
24
25 value = getattr(o, self.property_name)
26 return self.value_matcher.matches(value)
27
28 def describe_to(self, description):
29 description.append_text("an object with a property '") \
30 .append_text(self.property_name) \
31 .append_text("' matching ") \
32 .append_description_of(self.value_matcher)
33
34 def describe_mismatch(self, item, mismatch_description):
35 if item is None:
36 mismatch_description.append_text('was None')
37 return
38
39 if not hasattr(item, self.property_name):
40 mismatch_description.append_value(item) \
41 .append_text(' did not have the ') \
42 .append_value(self.property_name) \
43 .append_text(' property')
44 return
45
46 mismatch_description.append_text('property ').append_value(self.property_name).append_text(' ')
47 value = getattr(item, self.property_name)
48 self.value_matcher.describe_mismatch(value, mismatch_description)
49
50 def __str__(self):
51 d = StringDescription()
52 self.describe_to(d)
53 return str(d)
54
55
56 def has_property(name, match=None):
57 """Matches if object has a property with a given name whose value satisfies
58 a given matcher.
59
60 :param name: The name of the property.
61 :param match: Optional matcher to satisfy.
62
63 This matcher determines if the evaluated object has a property with a given
64 name. If no such property is found, ``has_property`` is not satisfied.
65
66 If the property is found, its value is passed to a given matcher for
67 evaluation. If the ``match`` argument is not a matcher, it is implicitly
68 wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to
69 check for equality.
70
71 If the ``match`` argument is not provided, the
72 :py:func:`~hamcrest.core.core.isanything.anything` matcher is used so that
73 ``has_property`` is satisfied if a matching property is found.
74
75 Examples::
76
77 has_property('name', starts_with('J'))
78 has_property('name', 'Jon')
79 has_property('name')
80
81 """
82
83 if match is None:
84 match = anything()
85
86 return IsObjectWithProperty(name, wrap_shortcut(match))
87
88
89 def has_properties(*keys_valuematchers, **kv_args):
90 """Matches if an object has properties satisfying all of a dictionary
91 of string property names and corresponding value matchers.
92
93 :param matcher_dict: A dictionary mapping keys to associated value matchers,
94 or to expected values for
95 :py:func:`~hamcrest.core.core.isequal.equal_to` matching.
96
97 Note that the keys must be actual keys, not matchers. Any value argument
98 that is not a matcher is implicitly wrapped in an
99 :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
100 equality.
101
102 Examples::
103
104 has_properties({'foo':equal_to(1), 'bar':equal_to(2)})
105 has_properties({'foo':1, 'bar':2})
106
107 ``has_properties`` also accepts a list of keyword arguments:
108
109 .. function:: has_properties(keyword1=value_matcher1[, keyword2=value_matcher2[, ...]])
110
111 :param keyword1: A keyword to look up.
112 :param valueMatcher1: The matcher to satisfy for the value, or an expected
113 value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching.
114
115 Examples::
116
117 has_properties(foo=equal_to(1), bar=equal_to(2))
118 has_properties(foo=1, bar=2)
119
120 Finally, ``has_properties`` also accepts a list of alternating keys and their
121 value matchers:
122
123 .. function:: has_properties(key1, value_matcher1[, ...])
124
125 :param key1: A key (not a matcher) to look up.
126 :param valueMatcher1: The matcher to satisfy for the value, or an expected
127 value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching.
128
129 Examples::
130
131 has_properties('foo', equal_to(1), 'bar', equal_to(2))
132 has_properties('foo', 1, 'bar', 2)
133
134 """
135 if len(keys_valuematchers) == 1:
136 try:
137 base_dict = keys_valuematchers[0].copy()
138 for key in base_dict:
139 base_dict[key] = wrap_shortcut(base_dict[key])
140 except AttributeError:
141 raise ValueError('single-argument calls to has_properties must pass a dict as the argument')
142 else:
143 if len(keys_valuematchers) % 2:
144 raise ValueError('has_properties requires key-value pairs')
145 base_dict = {}
146 for index in range(int(len(keys_valuematchers) / 2)):
147 base_dict[keys_valuematchers[2 * index]] = wrap_shortcut(keys_valuematchers[2 * index + 1])
148
149 for key, value in kv_args.items():
150 base_dict[key] = wrap_shortcut(value)
151
152 return all_of(*[has_property(property_name, property_value_matcher) for \
153 property_name, property_value_matcher in base_dict.items()])
0 from hamcrest.core.base_matcher import BaseMatcher
1 from hamcrest.core.helpers.wrap_matcher import wrap_matcher
2
3 __author__ = "Jon Reid"
4 __copyright__ = "Copyright 2011 hamcrest.org"
5 __license__ = "BSD, see License.txt"
6
7
8 class HasString(BaseMatcher):
9
10 def __init__(self, str_matcher):
11 self.str_matcher = str_matcher
12
13 def _matches(self, item):
14 return self.str_matcher.matches(str(item))
15
16 def describe_to(self, description):
17 description.append_text('an object with str ') \
18 .append_description_of(self.str_matcher)
19
20
21 def has_string(match):
22 """Matches if ``str(item)`` satisfies a given matcher.
23
24 :param match: The matcher to satisfy, or an expected value for
25 :py:func:`~hamcrest.core.core.isequal.equal_to` matching.
26
27 This matcher invokes the :py:func:`str` function on the evaluated object to
28 get its length, passing the result to a given matcher for evaluation. If
29 the ``match`` argument is not a matcher, it is implicitly wrapped in an
30 :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
31 equality.
32
33 Examples::
34
35 has_string(starts_with('foo'))
36 has_string('bar')
37
38 """
39 return HasString(wrap_matcher(match))
0 """Matchers that perform text comparisons."""
1
2 from isequal_ignoring_case import equal_to_ignoring_case
3 from isequal_ignoring_whitespace import equal_to_ignoring_whitespace
4 from stringcontains import contains_string
5 from stringendswith import ends_with
6 from stringstartswith import starts_with
7 from stringmatches import matches_regexp
8 from stringcontainsinorder import string_contains_in_order
9
10 __author__ = "Jon Reid"
11 __copyright__ = "Copyright 2011 hamcrest.org"
12 __license__ = "BSD, see License.txt"
0 from hamcrest.core.base_matcher import BaseMatcher
1
2 __author__ = "Jon Reid"
3 __copyright__ = "Copyright 2011 hamcrest.org"
4 __license__ = "BSD, see License.txt"
5
6
7 class IsEqualIgnoringCase(BaseMatcher):
8
9 def __init__(self, string):
10 if not isinstance(string, basestring):
11 raise TypeError('IsEqualIgnoringCase requires string')
12 self.original_string = string
13 self.lowered_string = string.lower()
14
15 def _matches(self, item):
16 if not isinstance(item, basestring):
17 return False
18 return self.lowered_string == item.lower()
19
20 def describe_to(self, description):
21 description.append_description_of(self.original_string) \
22 .append_text(' ignoring case')
23
24
25 def equal_to_ignoring_case(string):
26 """Matches if object is a string equal to a given string, ignoring case
27 differences.
28
29 :param string: The string to compare against as the expected value.
30
31 This matcher first checks whether the evaluated object is a string. If so,
32 it compares it with ``string``, ignoring differences of case.
33
34 Example::
35
36 equal_to_ignoring_case("hello world")
37
38 will match "heLLo WorlD".
39
40 """
41 return IsEqualIgnoringCase(string)
0 from hamcrest.core.base_matcher import BaseMatcher
1
2 __author__ = "Jon Reid"
3 __copyright__ = "Copyright 2011 hamcrest.org"
4 __license__ = "BSD, see License.txt"
5
6
7 def stripspace(string):
8 result = ''
9 last_was_space = True
10 for character in string:
11 if character.isspace():
12 if not last_was_space:
13 result += ' '
14 last_was_space = True
15 else:
16 result += character
17 last_was_space = False
18 return result.strip()
19
20
21 class IsEqualIgnoringWhiteSpace(BaseMatcher):
22
23 def __init__(self, string):
24 if not isinstance(string, basestring):
25 raise TypeError('IsEqualIgnoringWhiteSpace requires string')
26 self.original_string = string
27 self.stripped_string = stripspace(string)
28
29 def _matches(self, item):
30 if not isinstance(item, basestring):
31 return False
32 return self.stripped_string == stripspace(item)
33
34 def describe_to(self, description):
35 description.append_description_of(self.original_string) \
36 .append_text(' ignoring whitespace')
37
38
39 def equal_to_ignoring_whitespace(string):
40 """Matches if object is a string equal to a given string, ignoring
41 differences in whitespace.
42
43 :param string: The string to compare against as the expected value.
44
45 This matcher first checks whether the evaluated object is a string. If so,
46 it compares it with ``string``, ignoring differences in runs of whitespace.
47
48 Example::
49
50 equal_to_ignoring_whitespace("hello world")
51
52 will match ``"hello world"``.
53
54 """
55 return IsEqualIgnoringWhiteSpace(string)
0 from hamcrest.library.text.substringmatcher import SubstringMatcher
1 from hamcrest.core.helpers.hasmethod import hasmethod
2
3 __author__ = "Jon Reid"
4 __copyright__ = "Copyright 2011 hamcrest.org"
5 __license__ = "BSD, see License.txt"
6
7
8 class StringContains(SubstringMatcher):
9
10 def __init__(self, substring):
11 super(StringContains, self).__init__(substring)
12
13 def _matches(self, item):
14 if not hasmethod(item, 'find'):
15 return False
16 return item.find(self.substring) >= 0
17
18 def relationship(self):
19 return 'containing'
20
21
22 def contains_string(substring):
23 """Matches if object is a string containing a given string.
24
25 :param string: The string to search for.
26
27 This matcher first checks whether the evaluated object is a string. If so,
28 it checks whether it contains ``string``.
29
30 Example::
31
32 contains_string("def")
33
34 will match "abcdefg".
35
36 """
37 return StringContains(substring)
0 from hamcrest.core.base_matcher import BaseMatcher
1 from hamcrest.core.helpers.hasmethod import hasmethod
2
3 __author__ = "Romilly Cocking"
4 __copyright__ = "Copyright 2011 hamcrest.org"
5 __license__ = "BSD, see License.txt"
6
7
8 class StringContainsInOrder(BaseMatcher):
9
10 def __init__(self, *substrings):
11 for substring in substrings:
12 if not isinstance(substring, basestring):
13 raise TypeError(self.__class__.__name__
14 + ' requires string arguments')
15 self.substrings = substrings
16
17 def _matches(self, item):
18 if not hasmethod(item, 'find'):
19 return False
20 from_index = 0
21 for substring in self.substrings:
22 from_index = item.find(substring, from_index)
23 if from_index == -1:
24 return False
25 return True
26
27 def describe_to(self, description):
28 description.append_list('a string containing ', ', ', ' in order',
29 self.substrings)
30
31
32 def string_contains_in_order(*substrings):
33 """Matches if object is a string containing a given list of substrings in
34 relative order.
35
36 :param string1,...: A comma-separated list of strings.
37
38 This matcher first checks whether the evaluated object is a string. If so,
39 it checks whether it contains a given list of strings, in relative order to
40 each other. The searches are performed starting from the beginning of the
41 evaluated string.
42
43 Example::
44
45 string_contains_in_order("bc", "fg", "jkl")
46
47 will match "abcdefghijklm".
48
49 """
50 return StringContainsInOrder(*substrings)
0 from hamcrest.library.text.substringmatcher import SubstringMatcher
1 from hamcrest.core.helpers.hasmethod import hasmethod
2
3 __author__ = "Jon Reid"
4 __copyright__ = "Copyright 2011 hamcrest.org"
5 __license__ = "BSD, see License.txt"
6
7
8 class StringEndsWith(SubstringMatcher):
9
10 def __init__(self, substring):
11 super(StringEndsWith, self).__init__(substring)
12
13 def _matches(self, item):
14 if not hasmethod(item, 'endswith'):
15 return False
16 return item.endswith(self.substring)
17
18 def relationship(self):
19 return 'ending with'
20
21
22 def ends_with(string):
23 """Matches if object is a string ending with a given string.
24
25 :param string: The string to search for.
26
27 This matcher first checks whether the evaluated object is a string. If so,
28 it checks if ``string`` matches the ending characters of the evaluated
29 object.
30
31 Example::
32
33 ends_with("bar")
34
35 will match "foobar".
36
37 """
38 return StringEndsWith(string)
0 from hamcrest.core.base_matcher import BaseMatcher
1 from hamcrest.core.helpers.hasmethod import hasmethod
2 import re
3
4 __author__ = "Chris Rose"
5 __copyright__ = "Copyright 2011 hamcrest.org"
6 __license__ = "BSD, see License.txt"
7
8
9 class StringMatchesPattern(BaseMatcher):
10
11 def __init__(self, pattern):
12 self.pattern = pattern
13
14 def describe_to(self, description):
15 description.append_text("a string matching '") \
16 .append_text(self.pattern.pattern) \
17 .append_text("'")
18
19 def _matches(self, item):
20 return self.pattern.search(item) is not None
21
22
23 def matches_regexp(pattern):
24 """Matches if object is a string containing a match for a given regular
25 expression.
26
27 :param pattern: The regular expression to search for.
28
29 This matcher first checks whether the evaluated object is a string. If so,
30 it checks if the regular expression ``pattern`` matches anywhere within the
31 evaluated object.
32
33 """
34 if isinstance(pattern, basestring):
35 pattern = re.compile(pattern)
36
37 return StringMatchesPattern(pattern)
0 __author__ = "Jon Reid"
1 __copyright__ = "Copyright 2011 hamcrest.org"
2 __license__ = "BSD, see License.txt"
3
4 from hamcrest.library.text.substringmatcher import SubstringMatcher
5 from hamcrest.core.helpers.hasmethod import hasmethod
6
7
8 class StringStartsWith(SubstringMatcher):
9
10 def __init__(self, substring):
11 super(StringStartsWith, self).__init__(substring)
12
13 def _matches(self, item):
14 if not hasmethod(item, 'startswith'):
15 return False
16 return item.startswith(self.substring)
17
18 def relationship(self):
19 return 'starting with'
20
21
22 def starts_with(substring):
23 """Matches if object is a string starting with a given string.
24
25 :param string: The string to search for.
26
27 This matcher first checks whether the evaluated object is a string. If so,
28 it checks if ``string`` matches the beginning characters of the evaluated
29 object.
30
31 Example::
32
33 starts_with("foo")
34
35 will match "foobar".
36
37 """
38 return StringStartsWith(substring)
0 from hamcrest.core.base_matcher import BaseMatcher
1
2 __author__ = "Jon Reid"
3 __copyright__ = "Copyright 2011 hamcrest.org"
4 __license__ = "BSD, see License.txt"
5
6
7 class SubstringMatcher(BaseMatcher):
8
9 def __init__(self, substring):
10 if not isinstance(substring, basestring):
11 raise TypeError(self.__class__.__name__ + ' requires string')
12 self.substring = substring
13
14 def describe_to(self, description):
15 description.append_text('a string ') \
16 .append_text(self.relationship()) \
17 .append_text(' ') \
18 .append_description_of(self.substring)