{ "info": { "author": "Vitaliy Zakaznikov", "author_email": "vzakaznikov@testflows.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 2 - Pre-Alpha", "License :: OSI Approved :: Apache Software License", "Operating System :: POSIX :: Linux", "Programming Language :: Python :: 3" ], "description": "TestFlows - Asserts\n===================\n\n.. image:: https://raw.githubusercontent.com/testflows/TestFlows-ArtWork/master/images/testbug-laptop-testflows.png\n :width: 100%\n :alt: test bug\n :align: center\n\n**The asserts module is still work in progress and is currently under development.\nPlease use it only for reference.**\n\nNo magic, intuitive assertion library with descriptive error messages.\nWorks with Python's `assert statement`_ and is inspired by pytest_\nsupport for assertions and `grappa-py/grappa`_ descriptive error messages.\n\nCurrently supports only Python 3.6 or above.\n\nWhy\n***\n\n* No special assertion methods.\n Uses the default `assert statement`_.\n* No magic.\n Assertion statements are not modified and the default AssertionError_\n class is not overridden.\n* High performance.\n No extra code is executed if the assertion does not fail unless the assertion has side effects.\n* No external dependencies.\n* Simple and clean API.\n* Compatible with most Python test frameworks.\n\nUsage\n*****\n\nUse **error** for a single assert statement\n\n.. code-block:: python\n\n from testflows.asserts import error\n\n assert 1 == 1, error()\n\nor use **errors** context manager to wrap multiple assert statements\n\n.. code-block:: python\n\n from testflows.asserts import errors\n\n with errors():\n assert 1 == 1\n assert 2 == 2\n\nand if you don't want to abort when an assertion fails and would like to\nkeep going then the **errors** context manager supports soft assertions through it's\n**error** method.\n\n.. code-block:: python\n\n from testflows.asserts import errors\n\n with errors() as soft:\n with soft.error():\n assert 1 == 2\n assert 2 == 2\n\nWhen an assertion fails a descriptive error message is produced.\nFor example\n\n .. code-block:: python\n\n from testflows.asserts import error\n\n assert 1 == 2, error()\n\nproduces the following output\n\n .. code-block:: bash\n\n AssertionError: Oops! Assertion failed\n\n The following assertion was not satisfied\n assert 1 == 2, error()\n\n Assertion values\n assert 1 == 2, error()\n ^ is = False\n assert 1 == 2, error()\n ^ is False\n\n Where\n File 't.py', line 3 in ''\n\n 0|\n 1| from testflows.asserts import error\n 2|\n 3|> assert 1 == 2, error()\n\nHow\n***\n\nThe **asserts** module works similarly to the old implementation of\npytest_ assertions. If the assertion fails, the `assert statement`_ is reinterpreted\nto produce a detailed error message.\n\n Therefore, if the assertion statement has a side effect it might not\n work as expected when an assertion fails.\n\nIn the pytest_ framework, this problem_ is solved\nby rewriting the original assertion.\nThe **asserts** module solves this problem_ by explicitly using **values** context manager\nto store the values of the expression that has a side effect.\n\nInstallation\n************\n\n.. code-block:: bash\n\n $ ./build; ./install\n\n\nwhere\n\n.. code-block:: bash\n\n $ ./build\n\ncreates a pip installable package in *./dist*, for example\n\n.. code-block:: bash\n\n $ ls dist/\n testflows.asserts-4.1.190811.155018.tar.gz\n\nand\n\n.. code-block:: bash\n\n $ ./install\n\nuses *sudo pip install* command to perform the system-wide installation.\n\nAssertions with side-effects\n****************************\n\nIf assertion has side effects then **values** context manager can be used to\naddress this problem_.\n\nThe example below demonstrates the problem_.\n\n.. code-block:: python\n\n from testflows.asserts import error\n\n buf = [1]\n assert buf.append(2) and buf, error()\n\n\nIn the code above, the assertion fails and the **buf** list is modified twice. Once\nwhen the assertion fails and once when the assertion is reinterpreted when\n**error()** method is evaluated.\n\nThe error message that is produced shows the problem_\n\n.. code-block:: bash\n\n The following assertion was not satisfied\n assert buf.append(2) and buf, error()\n\n Assertion values\n assert buf.append(2) and buf, error()\n ^ is [1, 2, 2]\n assert buf.append(2) and buf, error()\n ^ is = \n assert buf.append(2) and buf, error()\n ^ is = None\n assert buf.append(2) and buf, error()\n ^ is [1, 2, 2]\n assert buf.append(2) and buf, error()\n ^ is = None\n assert buf.append(2) and buf, error()\n ^ is False\n\n Where\n File 't.py', line 4 in ''\n\n 1| from testflows.asserts import error\n 2|\n 3| buf = [1]\n 4|> assert buf.append(2) and buf, error()\n\nspecifically, the lines below show that value of **buf** is [1,2,2] instead\nof the desired value of [1,2]\n\n.. code-block:: bash\n\n Assertion values\n assert buf.append(2) and buf, error()\n ^ is [1, 2, 2]\n\nIn order to work around this problem_, **values** context manager can be used\nas follows\n\n.. code-block:: python\n\n from testflows.asserts import values, error\n\n buf = [1]\n with values() as that:\n assert that(buf.append(2)) and buf, error()\n\n\n\nand it will produce the error message\n\n.. code-block:: bash\n\n The following assertion was not satisfied\n assert that(buf.append(2)) and buf, error()\n\n Assertion values\n assert that(buf.append(2)) and buf, error()\n ^ is = None\n assert that(buf.append(2)) and buf, error()\n ^ is [1, 2]\n assert that(buf.append(2)) and buf, error()\n ^ is = None\n assert that(buf.append(2)) and buf, error()\n ^ is False\n\n Where\n File 't.py', line 5 in ''\n\n 1| from testflows.asserts import values, error\n 2|\n 3| buf = [1]\n 4| with values() as that:\n 5|> assert that(buf.append(2)) and buf, error()\n\nthe lines below show that the **buf** list has the expected value of [1,2]\n\n.. code-block:: bash\n\n assert that(buf.append(2)) and buf, error()\n ^ is [1, 2]\n\nthis is because the expression passed to **that** is not reinterpreted and only the\nresult of the expression is stored and used during the generation of the error message.\n\n The explicit use of **values** context manager provides a simple solution without\n any need to rewrite the original assertion statement.\n\n.. _problem: http://pybites.blogspot.com/2011/07/behind-scenes-of-pytests-new-assertion.html\n.. _AssertionError: https://docs.python.org/3/library/exceptions.html#AssertionError\n.. _`assert statement`: https://docs.python.org/3/reference/simple_stmts.html#assert\n.. _`grappa-py/grappa`: https://github.com/grappa-py/grappa\n.. _pytest: https://docs.pytest.org/en/latest/assert.html", "description_content_type": "text/x-rst", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/testflows/testflows-asserts", "keywords": "", "license": "Apache-2.0", "maintainer": "", "maintainer_email": "", "name": "testflows.asserts", "package_url": "https://pypi.org/project/testflows.asserts/", "platform": "", "project_url": "https://pypi.org/project/testflows.asserts/", "project_urls": { "Homepage": "https://github.com/testflows/testflows-asserts" }, "release_url": "https://pypi.org/project/testflows.asserts/5.3.191019.1125113/", "requires_dist": null, "requires_python": ">=3.6", "summary": "TestFlows - Asserts Assertion Library", "version": "5.3.191019.1125113" }, "last_serial": 5999774, "releases": { "5.2.191016.1221916": [ { "comment_text": "", "digests": { "md5": "bfb5ae0d61a3e8dd44e00ecd853c34a3", "sha256": "c62adb9487c4d84f6c988616733e90e01f05572b7ad589c375660b14f9b60e58" }, "downloads": -1, "filename": "testflows.asserts-5.2.191016.1221916.tar.gz", "has_sig": false, "md5_digest": "bfb5ae0d61a3e8dd44e00ecd853c34a3", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 9604, "upload_time": "2019-10-16T22:19:23", "url": "https://files.pythonhosted.org/packages/13/3e/0694f9682290ece341e165032d7d37e27c411abf1fec55c54e842747c2d5/testflows.asserts-5.2.191016.1221916.tar.gz" } ], "5.3.191019.1121011": [ { "comment_text": "", "digests": { "md5": "8707a9aac878c06c1f48448aad7822dc", "sha256": "9a41324cd041d35164d81c47dfab9f39f4930aeef801ff8d3329e67d0462277d" }, "downloads": -1, "filename": "testflows.asserts-5.3.191019.1121011.tar.gz", "has_sig": false, "md5_digest": "8707a9aac878c06c1f48448aad7822dc", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 11687, "upload_time": "2019-10-19T12:10:22", "url": "https://files.pythonhosted.org/packages/68/e2/420636d19de523115544ce4e0d5baddfd12518a0bc8861802404241d1c6f/testflows.asserts-5.3.191019.1121011.tar.gz" } ], "5.3.191019.1125113": [ { "comment_text": "", "digests": { "md5": "c0c516930f652ba5c22a7e0084ad21f6", "sha256": "ec4db0ba4f09c97c48a254bb1d5b5bbb9a7e7f05213fbc946a0298e90ba46e57" }, "downloads": -1, "filename": "testflows.asserts-5.3.191019.1125113.tar.gz", "has_sig": false, "md5_digest": "c0c516930f652ba5c22a7e0084ad21f6", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 11698, "upload_time": "2019-10-19T12:51:21", "url": "https://files.pythonhosted.org/packages/7d/89/69111f1d4903e90e746f4036586705b47b43d371e8f0782d1cb1eabbcbb2/testflows.asserts-5.3.191019.1125113.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "c0c516930f652ba5c22a7e0084ad21f6", "sha256": "ec4db0ba4f09c97c48a254bb1d5b5bbb9a7e7f05213fbc946a0298e90ba46e57" }, "downloads": -1, "filename": "testflows.asserts-5.3.191019.1125113.tar.gz", "has_sig": false, "md5_digest": "c0c516930f652ba5c22a7e0084ad21f6", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 11698, "upload_time": "2019-10-19T12:51:21", "url": "https://files.pythonhosted.org/packages/7d/89/69111f1d4903e90e746f4036586705b47b43d371e8f0782d1cb1eabbcbb2/testflows.asserts-5.3.191019.1125113.tar.gz" } ] }