{ "info": { "author": "Amino, Inc", "author_email": "foss@amino.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Framework :: Pytest", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Software Development :: Testing" ], "description": "=============\npytest-honors\n=============\n\n.. image:: https://img.shields.io/pypi/v/pytest-honors.svg\n :target: https://pypi.org/project/pytest-honors\n :alt: PyPI version\n\n.. image:: https://img.shields.io/pypi/pyversions/pytest-honors.svg\n :target: https://pypi.org/project/pytest-honors\n :alt: Python versions\n\n.. image:: https://travis-ci.org/aminohealth/pytest-honors.svg?branch=master\n :target: https://travis-ci.org/aminohealth/pytest-honors\n :alt: See Build Status on Travis CI\n\n.. image:: https://ci.appveyor.com/api/projects/status/github/kstrauser/pytest-honors-p7p8g?branch=master\n :target: https://ci.appveyor.com/project/kstrauser/pytest-honors-p7p8g/branch/master\n :alt: See Build Status on AppVeyor\n\nReport on tests that honor constraints, and guard against regressions\n\n----\n\nIntro\n-----\n\npytest-honors is a `pytest`_ plugin for automatically generating reports showing which of your project's unit tests \"honor\" (or \"prove\" or \"demonstrate\" or \"support\") various constraints that you care about. It can also be integrated with your build pipeline to make sure that you never accidentally remove the tests that are most important to you.\n\nBelow is a summary of features. More information is available at the `pytest-honors documentation`_ page.\n\nFeatures\n--------\n\n* Lightning fast! Since it piggybacks onto pytest's own test discovery and reporting system, it adds almost no measurable overhead to your testing process.\n* Generate nicely human-readable Markdown reports, suitable for handing to an auditor.\n* Automatically ensure that your test coverage only ever increases with time. Fixed things stay fixed!\n* Comes with ISO 27001 control definitions (but it's super easy to add your own).\n\n\nRequirements\n------------\n\n* pytest 3.5.0 or newer.\n\n\nInstallation\n------------\n\nYou can install \"pytest-honors\" via `pip`_ from `PyPI`_::\n\n $ pip install pytest-honors\n\n\nUsage\n-----\n\nYou've written several thousand unit tests, but you don't know which are actually *important* to you. Your team could laboriously struggle to keep docs up to date, but realistically that almost never works out as hoped. Even if your documentation is perfect, developers in the middle of a large refactoring project don't want to flip between static text and their code.\n\npytest-honors wants to help you. For example, given this code::\n\n import pytest\n from pytest_honors.constraints import ConstraintsGroup\n\n class MyControls(ConstraintsGroup):\n PasswordsMustBeGood = \"We don't want bad passwords\"\n EmailAddressesMustBeUnique = \"No two users may have the same email\"\n\n @pytest.mark.honors(MyControls.PasswordsMustBeGood)\n def test_password_strength():\n with pytest.raises(ValueError):\n check_password(\"12345\")\n\n @pytest.mark.honors(MyControls.EmailAddressesMustBeUnique)\n def test_unique_email():\n add_account(\"User One\", \"spam@example.com\")\n with pytest.raises(ValueError):\n add_account(\"User Two\", \"spam@example.com\")\n\nIn the language of pytest-honors, we say that ``test_password_string`` \"honors\" the PasswordsMustBeGood constraint and that ``test_unique_email`` honors the EmailAddressesMustBeUnique constraint. This is valuable on its own as developers can tell at a glance that each test actually matters to the overall design of the system, and they're not just there because a new boss wants everyone to reach 100% test coverage. By moving important documentation to a machine-readable format that lives next to the code, we can put that information to work to give you some very useful tools.\n\nWhen run like ``pytest --honors-report-markdown report.md``, we can get nice, human-readable documentation like:\n\n.. code-block:: text\n\n # MyControls - An enumeration.\n\n ## EmailAddressesMustBeUnique: No two users may have the same email\n\n Supporting evidence:\n\n - Name: test_unique_email\n Explanation: \"None\"\n Path: tests/test_important_stuff.py::test_unique_email\n Result: passed\n\n ## PasswordsMustBeGood: We don't want bad passwords\n\n Supporting evidence:\n\n - Name: test_password_strength\n Explanation: \"None\"\n Path: tests/test_important_stuff.py::test_password_strength\n Result: passed\n\nThis shows us all controls that are honored by the tests that we ran. Want to show your auditor that you're checking important controls in your code? Now you have evidence.\n\nWhen run like ``pytest --honors-store-counts``, pytest-honors saves the number of tests honoring each constraint. Later you can run ``pytest --honors-regression-fail``, and if the coverage for any controls has decreased since the last test run, then pytest fails. Suppose an intern deletes the ``test_unique_email`` unit test. That results in the error::\n\n ValueError: ['Constraint MyControls.EmailAddressesMustBeUnique honorers count dropped from 1 to 0']\n\nYou can integrate this in your CI pipeline and know that a rogue developer isn't deleting the constraints you care about.\n\n\nContributing\n------------\n\nContributions are very welcome. Tests can be run with `tox`_, please ensure\nthe coverage at least stays the same before you submit a pull request.\n\nEspecially appreciated, and requiring the least amount of coding experience, would be other constraint definitions so that new users have a pleasant \"batteries included\" experience.\n\n\nLicense\n-------\n\nDistributed under the terms of the `MIT`_ license, \"pytest-honors\" is free and open source software.\n\n\nIssues\n------\n\nIf you encounter any problems, please `file an issue`_ along with a detailed description.\n\n.. _`MIT`: http://opensource.org/licenses/MIT\n.. _`file an issue`: https://github.com/aminohealth/pytest-honors/issues\n.. _`pytest`: https://github.com/pytest-dev/pytest\n.. _`tox`: https://tox.readthedocs.io/en/latest/\n.. _`pip`: https://pypi.org/project/pip/\n.. _`PyPI`: https://pypi.org/project\n.. _`pytest-honors documentation`: https://pytest-honors.readthedocs.io/en/latest/\n\n\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/aminohealth/pytest-honors", "keywords": "", "license": "MIT", "maintainer": "Amino, Inc", "maintainer_email": "foss@amino.com", "name": "pytest-honors", "package_url": "https://pypi.org/project/pytest-honors/", "platform": "", "project_url": "https://pypi.org/project/pytest-honors/", "project_urls": { "Documentation": "https://pytest-honors.readthedocs.io/en/latest/", "Homepage": "https://github.com/aminohealth/pytest-honors" }, "release_url": "https://pypi.org/project/pytest-honors/0.1.4/", "requires_dist": [ "pytest (>=3.5.0)" ], "requires_python": ">=3, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", "summary": "Enforce coverage and report on tests that honor constraints", "version": "0.1.4" }, "last_serial": 5768517, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "0e0182baa4ed6ebcb95b4ccfb09ce687", "sha256": "96726fbea313c886df352408c37518ffa983c23588bb88c7043424a9f3eac59f" }, "downloads": -1, "filename": "pytest_honors-0.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "0e0182baa4ed6ebcb95b4ccfb09ce687", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", "size": 4659, "upload_time": "2019-09-01T03:23:38", "url": "https://files.pythonhosted.org/packages/8c/2c/ca1246f8abdf14772a5cdff4308ed5ad5baff80a31ebfea214be36ce697e/pytest_honors-0.1.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "4ffaf26c57ab521ce2b986f91347a513", "sha256": "55aaf826bc0ee43389fe994ba38efda8c4bff53f3c258d19768f2f6fe3bf686e" }, "downloads": -1, "filename": "pytest-honors-0.1.0.tar.gz", "has_sig": false, "md5_digest": "4ffaf26c57ab521ce2b986f91347a513", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", "size": 4826, "upload_time": "2019-09-01T03:23:41", "url": "https://files.pythonhosted.org/packages/ee/f1/419b7632944a909f404be2fdcc4621a07ca7c1eb8baad584310f06028877/pytest-honors-0.1.0.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "60c63b12a9662dfa83204ac612e3ff35", "sha256": "097620f8fe76b23b044ee5cc3dc5eb93d102aecb7f553f4fa658af43d69da2f1" }, "downloads": -1, "filename": "pytest_honors-0.1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "60c63b12a9662dfa83204ac612e3ff35", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", "size": 4738, "upload_time": "2019-09-01T03:38:45", "url": "https://files.pythonhosted.org/packages/01/d8/553b344a5907a81291fe4820d8aa33b03220012be2c64ce38f4bd4caa6d5/pytest_honors-0.1.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "40e34e2d9bc1d908c658cf2c2e479cd1", "sha256": "e3283c485926f892fc68c43c8a55e2be571630c7dfe2858e574474733715c680" }, "downloads": -1, "filename": "pytest-honors-0.1.1.tar.gz", "has_sig": false, "md5_digest": "40e34e2d9bc1d908c658cf2c2e479cd1", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", "size": 4936, "upload_time": "2019-09-01T03:38:47", "url": "https://files.pythonhosted.org/packages/b6/4b/ca13f4f833c465b0238ca1daee6da027e7a1a477111e645dd633445a3542/pytest-honors-0.1.1.tar.gz" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "2e94381a9dccd11d00a04dbf76458a06", "sha256": "adc067013127d6145ecfab12d6c67d2740dffc617fb2ad0ccc7ed1f0d46f21b8" }, "downloads": -1, "filename": "pytest_honors-0.1.2-py3-none-any.whl", "has_sig": false, "md5_digest": "2e94381a9dccd11d00a04dbf76458a06", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", "size": 4742, "upload_time": "2019-09-01T19:02:01", "url": "https://files.pythonhosted.org/packages/64/18/e4fcc1dc7bd6009c32fd66a1c7dfcc3f3f1fd861694d5ef8f444a36561b8/pytest_honors-0.1.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "4d4d3e7b482d6dc992c7ea2a0a75c48d", "sha256": "29131d7676c716604c2fdea6144a9100bb28dff82beee7c637bfeeaabba8fb84" }, "downloads": -1, "filename": "pytest-honors-0.1.2.tar.gz", "has_sig": false, "md5_digest": "4d4d3e7b482d6dc992c7ea2a0a75c48d", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", "size": 4944, "upload_time": "2019-09-01T19:02:03", "url": "https://files.pythonhosted.org/packages/1c/cf/339338041e668b9ad52597e5198748c31cc08439abc4e906ab611d5d28a5/pytest-honors-0.1.2.tar.gz" } ], "0.1.3": [ { "comment_text": "", "digests": { "md5": "06c704cf2e619566e2f9147a36ca40f0", "sha256": "087391168848fb05d68842edd18b096ad7819a5efb936eadb649ff1434cf3498" }, "downloads": -1, "filename": "pytest_honors-0.1.3-py3-none-any.whl", "has_sig": false, "md5_digest": "06c704cf2e619566e2f9147a36ca40f0", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", "size": 4740, "upload_time": "2019-09-02T00:00:03", "url": "https://files.pythonhosted.org/packages/b6/29/1d45ff7d59aedb7777c69aa670092d02c742872289eb49e1b7e0aeef95d8/pytest_honors-0.1.3-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "8b8425c81f3da6d8217b61c14424ecb4", "sha256": "f305f381b6c4445007e575efdf50f08aac8a0ad54307f9769b39d7d32032145c" }, "downloads": -1, "filename": "pytest-honors-0.1.3.tar.gz", "has_sig": false, "md5_digest": "8b8425c81f3da6d8217b61c14424ecb4", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", "size": 4943, "upload_time": "2019-09-02T00:00:05", "url": "https://files.pythonhosted.org/packages/62/31/e68ccf6ce47af971e55c32b94a53ecc82bb33550778c89bcd1c205405dad/pytest-honors-0.1.3.tar.gz" } ], "0.1.4": [ { "comment_text": "", "digests": { "md5": "6880b63d8d3e93f660c5bd920550b311", "sha256": "f38bcbb56a8818f17c23c07ceb9ad1b4f69b7b6325a36cafffe5c4094076f632" }, "downloads": -1, "filename": "pytest_honors-0.1.4-py3-none-any.whl", "has_sig": false, "md5_digest": "6880b63d8d3e93f660c5bd920550b311", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", "size": 10527, "upload_time": "2019-09-02T00:50:46", "url": "https://files.pythonhosted.org/packages/e1/da/59de553a4007b705290b15e091f087d611ffb38549f70a4a52830d8c9767/pytest_honors-0.1.4-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "503a2ac71fe58b5b43fb664980ac43af", "sha256": "50cc1c00a60c1d32cf1b5dfee152f37c7597107c96982d9a07f81dd68278be9a" }, "downloads": -1, "filename": "pytest-honors-0.1.4.tar.gz", "has_sig": false, "md5_digest": "503a2ac71fe58b5b43fb664980ac43af", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", "size": 12494, "upload_time": "2019-09-02T00:50:48", "url": "https://files.pythonhosted.org/packages/d2/b2/5678ff097acbfc4ace616b36aa33c71334ea4254763c6aca317b3f80f2f2/pytest-honors-0.1.4.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "6880b63d8d3e93f660c5bd920550b311", "sha256": "f38bcbb56a8818f17c23c07ceb9ad1b4f69b7b6325a36cafffe5c4094076f632" }, "downloads": -1, "filename": "pytest_honors-0.1.4-py3-none-any.whl", "has_sig": false, "md5_digest": "6880b63d8d3e93f660c5bd920550b311", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", "size": 10527, "upload_time": "2019-09-02T00:50:46", "url": "https://files.pythonhosted.org/packages/e1/da/59de553a4007b705290b15e091f087d611ffb38549f70a4a52830d8c9767/pytest_honors-0.1.4-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "503a2ac71fe58b5b43fb664980ac43af", "sha256": "50cc1c00a60c1d32cf1b5dfee152f37c7597107c96982d9a07f81dd68278be9a" }, "downloads": -1, "filename": "pytest-honors-0.1.4.tar.gz", "has_sig": false, "md5_digest": "503a2ac71fe58b5b43fb664980ac43af", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", "size": 12494, "upload_time": "2019-09-02T00:50:48", "url": "https://files.pythonhosted.org/packages/d2/b2/5678ff097acbfc4ace616b36aa33c71334ea4254763c6aca317b3f80f2f2/pytest-honors-0.1.4.tar.gz" } ] }