You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

353 lines
13 KiB

4 years ago
  1. Metadata-Version: 2.0
  2. Name: PyHamcrest
  3. Version: 1.9.0
  4. Summary: Hamcrest framework for matcher objects
  5. Home-page: https://github.com/hamcrest/PyHamcrest
  6. Author: Chris Rose
  7. Author-email: offline@offby1.net
  8. License: New BSD
  9. Download-URL: http://pypi.python.org/packages/source/P/PyHamcrest/PyHamcrest-1.9.0.tar.gz
  10. Keywords: hamcrest matchers pyunit unit test testing unittest unittesting
  11. Platform: All
  12. Classifier: Development Status :: 5 - Production/Stable
  13. Classifier: Environment :: Console
  14. Classifier: Intended Audience :: Developers
  15. Classifier: License :: OSI Approved :: BSD License
  16. Classifier: Natural Language :: English
  17. Classifier: Operating System :: OS Independent
  18. Classifier: Programming Language :: Python :: 2
  19. Classifier: Programming Language :: Python :: 2.7
  20. Classifier: Programming Language :: Python :: 3
  21. Classifier: Programming Language :: Python :: 3.4
  22. Classifier: Programming Language :: Python :: Implementation :: CPython
  23. Classifier: Programming Language :: Python :: Implementation :: Jython
  24. Classifier: Programming Language :: Python :: Implementation :: PyPy
  25. Classifier: Topic :: Software Development
  26. Classifier: Topic :: Software Development :: Quality Assurance
  27. Classifier: Topic :: Software Development :: Testing
  28. Provides: hamcrest
  29. Requires-Dist: setuptools
  30. Requires-Dist: six
  31. PyHamcrest
  32. ==========
  33. | |docs| |travis| |coveralls| |landscape| |scrutinizer| |codeclimate|
  34. | |version| |downloads| |wheel| |supported-versions| |supported-implementations|
  35. .. |docs| image:: https://readthedocs.org/projects/pyhamcrest/badge/?style=flat
  36. :target: https://pyhamcrest.readthedocs.org/
  37. :alt: Documentation Status
  38. .. |travis| image:: http://img.shields.io/travis/hamcrest/PyHamcrest/master.png?style=flat
  39. :alt: Travis-CI Build Status
  40. :target: https://travis-ci.org/hamcrest/PyHamcrest
  41. .. |appveyor| image:: https://ci.appveyor.com/api/projects/status/github/hamcrest/PyHamcrest?branch=master
  42. :alt: AppVeyor Build Status
  43. :target: https://ci.appveyor.com/project/hamcrest/PyHamcrest
  44. .. |coveralls| image:: http://img.shields.io/coveralls/hamcrest/PyHamcrest/master.png?style=flat
  45. :alt: Coverage Status
  46. :target: https://coveralls.io/r/hamcrest/PyHamcrest
  47. .. |landscape| image:: https://landscape.io/github/hamcrest/PyHamcrest/master/landscape.svg?style=flat
  48. :target: https://landscape.io/github/hamcrest/PyHamcrest/master
  49. :alt: Code Quality Status
  50. .. |codeclimate| image:: https://codeclimate.com/github/hamcrest/PyHamcrest/badges/gpa.svg
  51. :target: https://codeclimate.com/github/hamcrest/PyHamcrest
  52. :alt: Code Climate
  53. .. |version| image:: http://img.shields.io/pypi/v/PyHamcrest.png?style=flat
  54. :alt: PyPI Package latest release
  55. :target: https://pypi.python.org/pypi/PyHamcrest
  56. .. |downloads| image:: http://img.shields.io/pypi/dm/PyHamcrest.png?style=flat
  57. :alt: PyPI Package monthly downloads
  58. :target: https://pypi.python.org/pypi/PyHamcrest
  59. .. |wheel| image:: https://pypip.in/wheel/PyHamcrest/badge.png?style=flat
  60. :alt: PyPI Wheel
  61. :target: https://pypi.python.org/pypi/PyHamcrest
  62. .. |supported-versions| image:: https://pypip.in/py_versions/PyHamcrest/badge.png?style=flat
  63. :alt: Supported versions
  64. :target: https://pypi.python.org/pypi/PyHamcrest
  65. .. |supported-implementations| image:: https://pypip.in/implementation/PyHamcrest/badge.png?style=flat
  66. :alt: Supported imlementations
  67. :target: https://pypi.python.org/pypi/PyHamcrest
  68. .. |scrutinizer| image:: https://img.shields.io/scrutinizer/g/hamcrest/PyHamcrest/master.png?style=flat
  69. :alt: Scrtinizer Status
  70. :target: https://scrutinizer-ci.com/g/hamcrest/PyHamcrest/
  71. Introduction
  72. ============
  73. PyHamcrest is a framework for writing matcher objects, allowing you to
  74. declaratively define "match" rules. There are a number of situations where
  75. matchers are invaluable, such as UI validation, or data filtering, but it is in
  76. the area of writing flexible tests that matchers are most commonly used. This
  77. tutorial shows you how to use PyHamcrest for unit testing.
  78. When writing tests it is sometimes difficult to get the balance right between
  79. overspecifying the test (and making it brittle to changes), and not specifying
  80. enough (making the test less valuable since it continues to pass even when the
  81. thing being tested is broken). Having a tool that allows you to pick out
  82. precisely the aspect under test and describe the values it should have, to a
  83. controlled level of precision, helps greatly in writing tests that are "just
  84. right." Such tests fail when the behavior of the aspect under test deviates
  85. from the expected behavior, yet continue to pass when minor, unrelated changes
  86. to the behaviour are made.
  87. Installation
  88. ============
  89. Hamcrest can be installed using the usual Python packaging tools. It depends on
  90. distribute, but as long as you have a network connection when you install, the
  91. installation process will take care of that for you.
  92. My first PyHamcrest test
  93. ========================
  94. We'll start by writing a very simple PyUnit test, but instead of using PyUnit's
  95. ``assertEqual`` method, we'll use PyHamcrest's ``assert_that`` construct and
  96. the standard set of matchers:
  97. .. code:: python
  98. from hamcrest import *
  99. import unittest
  100. class BiscuitTest(unittest.TestCase):
  101. def testEquals(self):
  102. theBiscuit = Biscuit('Ginger')
  103. myBiscuit = Biscuit('Ginger')
  104. assert_that(theBiscuit, equal_to(myBiscuit))
  105. if __name__ == '__main__':
  106. unittest.main()
  107. The ``assert_that`` function is a stylized sentence for making a test
  108. assertion. In this example, the subject of the assertion is the object
  109. ``theBiscuit``, which is the first method parameter. The second method
  110. parameter is a matcher for ``Biscuit`` objects, here a matcher that checks one
  111. object is equal to another using the Python ``==`` operator. The test passes
  112. since the ``Biscuit`` class defines an ``__eq__`` method.
  113. If you have more than one assertion in your test you can include an identifier
  114. for the tested value in the assertion:
  115. .. code:: python
  116. assert_that(theBiscuit.getChocolateChipCount(), equal_to(10), 'chocolate chips')
  117. assert_that(theBiscuit.getHazelnutCount(), equal_to(3), 'hazelnuts')
  118. As a convenience, assert_that can also be used to verify a boolean condition:
  119. .. code:: python
  120. assert_that(theBiscuit.isCooked(), 'cooked')
  121. This is equivalent to the ``assert_`` method of unittest.TestCase, but because
  122. it's a standalone function, it offers greater flexibility in test writing.
  123. Predefined matchers
  124. ===================
  125. PyHamcrest comes with a library of useful matchers:
  126. * Object
  127. * ``equal_to`` - match equal object
  128. * ``has_length`` - match ``len()``
  129. * ``has_property`` - match value of property with given name
  130. * ``has_properties`` - match an object that has all of the given properties.
  131. * ``has_string`` - match ``str()``
  132. * ``instance_of`` - match object type
  133. * ``none``, ``not_none`` - match ``None``, or not ``None``
  134. * ``same_instance`` - match same object
  135. * ``calling, raises`` - wrap a method call and assert that it raises an exception
  136. * Number
  137. * ``close_to`` - match number close to a given value
  138. * ``greater_than``, ``greater_than_or_equal_to``, ``less_than``,
  139. ``less_than_or_equal_to`` - match numeric ordering
  140. * Text
  141. * ``contains_string`` - match part of a string
  142. * ``ends_with`` - match the end of a string
  143. * ``equal_to_ignoring_case`` - match the complete string but ignore case
  144. * ``equal_to_ignoring_whitespace`` - match the complete string but ignore extra whitespace
  145. * ``matches_regexp`` - match a regular expression in a string
  146. * ``starts_with`` - match the beginning of a string
  147. * ``string_contains_in_order`` - match parts of a string, in relative order
  148. * Logical
  149. * ``all_of`` - ``and`` together all matchers
  150. * ``any_of`` - ``or`` together all matchers
  151. * ``anything`` - match anything, useful in composite matchers when you don't care about a particular value
  152. * ``is_not`` - negate the matcher
  153. * Sequence
  154. * ``contains`` - exactly match the entire sequence
  155. * ``contains_inanyorder`` - match the entire sequence, but in any order
  156. * ``has_item`` - match if given item appears in the sequence
  157. * ``has_items`` - match if all given items appear in the sequence, in any order
  158. * ``is_in`` - match if item appears in the given sequence
  159. * ``only_contains`` - match if sequence's items appear in given list
  160. * ``empty`` - match if the sequence is empty
  161. * Dictionary
  162. * ``has_entries`` - match dictionary with list of key-value pairs
  163. * ``has_entry`` - match dictionary containing a key-value pair
  164. * ``has_key`` - match dictionary with a key
  165. * ``has_value`` - match dictionary with a value
  166. * Decorator
  167. * ``calling`` - wrap a callable in a deffered object, for subsequent matching on calling behaviour
  168. * ``raises`` - Ensure that a deferred callable raises as expected
  169. * ``described_as`` - give the matcher a custom failure description
  170. * ``is_`` - decorator to improve readability - see `Syntactic sugar` below
  171. The arguments for many of these matchers accept not just a matching value, but
  172. another matcher, so matchers can be composed for greater flexibility. For
  173. example, ``only_contains(less_than(5))`` will match any sequence where every
  174. item is less than 5.
  175. Syntactic sugar
  176. ===============
  177. PyHamcrest strives to make your tests as readable as possible. For example, the
  178. ``is_`` matcher is a wrapper that doesn't add any extra behavior to the
  179. underlying matcher. The following assertions are all equivalent:
  180. .. code:: python
  181. assert_that(theBiscuit, equal_to(myBiscuit))
  182. assert_that(theBiscuit, is_(equal_to(myBiscuit)))
  183. assert_that(theBiscuit, is_(myBiscuit))
  184. The last form is allowed since ``is_(value)`` wraps most non-matcher arguments
  185. with ``equal_to``. But if the argument is a type, it is wrapped with
  186. ``instance_of``, so the following are also equivalent:
  187. .. code:: python
  188. assert_that(theBiscuit, instance_of(Biscuit))
  189. assert_that(theBiscuit, is_(instance_of(Biscuit)))
  190. assert_that(theBiscuit, is_(Biscuit))
  191. *Note that PyHamcrest's ``is_`` matcher is unrelated to Python's ``is``
  192. operator. The matcher for object identity is ``same_instance``.*
  193. Writing custom matchers
  194. =======================
  195. PyHamcrest comes bundled with lots of useful matchers, but you'll probably find
  196. that you need to create your own from time to time to fit your testing needs.
  197. This commonly occurs when you find a fragment of code that tests the same set
  198. of properties over and over again (and in different tests), and you want to
  199. bundle the fragment into a single assertion. By writing your own matcher you'll
  200. eliminate code duplication and make your tests more readable!
  201. Let's write our own matcher for testing if a calendar date falls on a Saturday.
  202. This is the test we want to write:
  203. .. code:: python
  204. def testDateIsOnASaturday(self):
  205. d = datetime.date(2008, 04, 26)
  206. assert_that(d, is_(on_a_saturday()))
  207. And here's the implementation:
  208. .. code:: python
  209. from hamcrest.core.base_matcher import BaseMatcher
  210. from hamcrest.core.helpers.hasmethod import hasmethod
  211. class IsGivenDayOfWeek(BaseMatcher):
  212. def __init__(self, day):
  213. self.day = day # Monday is 0, Sunday is 6
  214. def _matches(self, item):
  215. if not hasmethod(item, 'weekday'):
  216. return False
  217. return item.weekday() == self.day
  218. def describe_to(self, description):
  219. day_as_string = ['Monday', 'Tuesday', 'Wednesday', 'Thursday',
  220. 'Friday', 'Saturday', 'Sunday']
  221. description.append_text('calendar date falling on ') \
  222. .append_text(day_as_string[self.day])
  223. def on_a_saturday():
  224. return IsGivenDayOfWeek(5)
  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. .. code:: python
  231. assert_that(datetime.date(2008, 04, 06), is_(on_a_saturday()))
  232. fails with the message::
  233. AssertionError:
  234. Expected: is calendar date falling on Saturday
  235. got: <2008-04-06>
  236. Let's say this matcher is saved in a module named ``isgivendayofweek``. We
  237. could use it in our test by importing the factory function ``on_a_saturday``:
  238. .. code:: python
  239. from hamcrest import *
  240. import unittest
  241. from isgivendayofweek import on_a_saturday
  242. class DateTest(unittest.TestCase):
  243. def testDateIsOnASaturday(self):
  244. d = datetime.date(2008, 04, 26)
  245. assert_that(d, is_(on_a_saturday()))
  246. if __name__ == '__main__':
  247. unittest.main()
  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. More resources
  253. ==============
  254. * Documentation_
  255. * Package_
  256. * Sources_
  257. * Hamcrest_
  258. .. _Documentation: http://readthedocs.org/docs/pyhamcrest/en/V1.8.2/
  259. .. _Package: http://pypi.python.org/pypi/PyHamcrest
  260. .. _Sources: https://github.com/hamcrest/PyHamcrest
  261. .. _Hamcrest: http://hamcrest.org