{ "info": { "author": "Stefano Apostolico", "author_email": "s.apostolico@gmail.com", "bugtrack_url": null, "classifiers": [ "Environment :: Web Environment", "Framework :: Django", "Framework :: Django :: 1.10", "Framework :: Django :: 1.11", "Framework :: Django :: 2.0", "Intended Audience :: Developers", "Operating System :: OS Independent", "Programming Language :: Python :: 3.6" ], "description": "# DRF API Checker\n\n\n[![pypi-version]][pypi] \n[![travis-png-m]][travis-l-m] \n[![rtd-badge]][rtd-link]\n[![codecov-badge]][codecov]\n\n\nThis module offers some utilities to avoid unwanted changes in Django Rest Framework responses,\nso to keep stable contracts\n\nThe purpose is to guarantee that any code changes never introduce 'contract violations'\nchanging the Serialization behaviour.\n\n\nContract violations can happen when:\n\n- fields are removed from Serializer\n- field representation changes (ie. date/number format, )\n- Response status code changes (optional check)\n- Response headers change (optional check)\n\n\nHow it works:\n-------------\n\nFirst time the test run, the response and model instances are serialized and\nsaved on the disk; any further execution is checked against this first response.\n\nTest data are saved in the same directory where the test module lives,\nunder `_api_checker//`\n\nFields that cannot be checked by value (ie timestamps/last modified) can be tested writing\ncustom `assert_` methods.\n\nIn case of nested objects, method names must follow the field \"path\".\n(ie. `assert_permission_modified` vs `assert_modified`)\n\nThis module can also intercept when a field is added,\nin this case it is mandatory recreate stored test data; simply delete them from the disk\nor set `API_CHECKER_RESET` environment variable and run the test again,\n\n\nin case something goes wrong the output will be\n\n**Field values mismatch**\n\n AssertionError: View `` breaks the contract.\n Field `name` does not match.\n - expected: `Partner 0`\n - received: `Partner 11`\n\n\n**Field removed**\n\n AssertionError: View `` breaks the contract.\n Field `id` is missing in the new response\n\n\n**Field added**\n\n AssertionError: View `` returned more field than expected.\n Action needed api_customers.response.json need rebuild.\n New fields are:\n `['country']`\n\n\nHow To use it:\n--------------\n\n**unittest**\n\n\nUsing ApiCheckerMixin::\n\n class TestAPIAgreements(ApiCheckerMixin, TestCase):\n def get_fixtures(self):\n return {'customer': CustomerFactory()}\n\n def test_customer_detail(self):\n url = reverse(\"customer-detail\", args=[self.get_fixture('customer').pk])\n self.assertGET(url)\n\n\nUsing ApiCheckerBase metaclass\n\n\n class TestAPIIntervention(TestCase, metaclass=ApiCheckerBase):\n URLS = [\n reverse(\"intervention-list\"),\n reverse(\"intervention-detail\", args=[101]),\n ]\n\n def get_fixtures(cls):\n return {'intervention': InterventionFactory(id=101),\n 'result': ResultFactory(),\n }\n\nApiCheckerBase can produce API test with minimum effort but it offers less flexibility\nthan ApiCheckerMixin.\n\n**pytest**\n\n\npytest integration is provided by two helpers `frozenfixture` and `contract`::\n\n\n from django.urls import reverse\n from drf_api_checker.pytest import contract, frozenfixture\n\n\n @frozenfixture()\n def frozen_detail(db):\n from demo.factories import DetailFactory\n return DetailFactory()\n\n @contract()\n def test_url(frozen_detail):\n url = reverse(\"master-list\")\n return url\n\n\nCustom checks:\n--------------\n\nSometimes it is not possible to check a field by value but exists anyway a mechanism \nto check the contract (ie. `timestamp` field - _ignore for this example tools like [freezegun](https://github.com/spulec/freezegun)_)\n\nTo handle this situations you can write custom `Recorder` with specia `asserters`:\n\n\n from drf_api_checker.recorder import Recorder\n\n class TimestampRecorder(Recorder):\n \n def assert_last_modify_date(self, response: Response, stored: Response, path: str):\n value = response['last_modify_date']\n assert datetime.datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%fZ')\n\ncustom asserter is a method named `assert_`, in case of nested serializers\nyou can have more specific asserter using `assert__`\n\n\nLinks\n-----\n\n|||\n|--------------------|------------------------------------------------------------|\n| Develop | [![travis-png-d]][travis-l-d]|\n| Master | [![travis-png-m]][travis-l-m]|\n| Project home page: | https://github.com/saxix/drf-api-checker |\n| Issue tracker: | https://github.com/saxix/drf-api-checker/issues?sort |\n| Download: | http://pypi.python.org/pypi/drf-api-checker/ |\n| Documentation: | https://drf-api-checker.readthedocs.org/en/develop/ |\n\n\n\n[travis-png-m]: https://secure.travis-ci.org/saxix/drf-api-checker.svg?branch=master\n[travis-l-m]: https://travis-ci.org/saxix/drf-api-checker?branch=master\n\n[travis-png-d]: https://secure.travis-ci.org/saxix/drf-api-checker.svg?branch=develop\n[travis-l-d]: https://travis-ci.org/saxix/drf-api-checker?branch=develop\n\n[rtd-badge]: https://readthedocs.org/projects/drf-api-checker/badge/?version=master&style=plastic\n[rtd-link]: https://drf-api-checker.readthedocs.org/en/master/\n\n[codecov-badge]: https://codecov.io/gh/saxix/drf-api-checker/branch/develop/graph/badge.svg\n[codecov]: https://codecov.io/gh/saxix/drf-api-checker\n\n[pypi-version]: https://img.shields.io/pypi/v/drf-api-checker.svg\n[pypi]: https://pypi.org/project/drf-api-checker/", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/saxix/drf-api-checker", "keywords": "", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "drf-api-checker", "package_url": "https://pypi.org/project/drf-api-checker/", "platform": "linux", "project_url": "https://pypi.org/project/drf-api-checker/", "project_urls": { "Homepage": "https://github.com/saxix/drf-api-checker" }, "release_url": "https://pypi.org/project/drf-api-checker/0.8.0/", "requires_dist": null, "requires_python": "", "summary": "DjangoRestFramework API checker", "version": "0.8.0" }, "last_serial": 5837802, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "6090eb6873e904b7b9ff9a5202b45b04", "sha256": "df6d03805a2a2d2021f4c90f7fa8aa07dc068a8f4deecd42e4f29fe540d9535d" }, "downloads": -1, "filename": "drf-api-checker-0.1.0.tar.gz", "has_sig": false, "md5_digest": "6090eb6873e904b7b9ff9a5202b45b04", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17327, "upload_time": "2018-06-03T06:20:28", "url": "https://files.pythonhosted.org/packages/04/d0/32d49dbecc9afee9bafd8743b7a23cf0054cd908767774aac48af27edea5/drf-api-checker-0.1.0.tar.gz" } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "8bfdf9ea38f4069d5166481d08c56032", "sha256": "c44ce1b01bc6d6fae110715ee5633b9e113563c92f52c866ee011609b4e3b763" }, "downloads": -1, "filename": "drf-api-checker-0.2.0.tar.gz", "has_sig": false, "md5_digest": "8bfdf9ea38f4069d5166481d08c56032", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20417, "upload_time": "2018-06-03T16:51:02", "url": "https://files.pythonhosted.org/packages/82/dd/99f4900622b51b979c6d1fe15dfd4ffae3d1d6263f497dd31c702f568c1f/drf-api-checker-0.2.0.tar.gz" } ], "0.3.0": [ { "comment_text": "", "digests": { "md5": "3fee302374995d5c4de3090996565b21", "sha256": "56ffa0e579da8134130d3a1a27850d176b777b949816d90eea73917992115fb1" }, "downloads": -1, "filename": "drf-api-checker-0.3.0.tar.gz", "has_sig": false, "md5_digest": "3fee302374995d5c4de3090996565b21", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12362, "upload_time": "2018-06-22T09:42:02", "url": "https://files.pythonhosted.org/packages/66/39/2ec31709fe5593718aeec90ff785f45417df2e46977cb8885a7e8e6677c8/drf-api-checker-0.3.0.tar.gz" } ], "0.4.1": [ { "comment_text": "", "digests": { "md5": "5c9d5804acc8cb6e0e68d7828a17b950", "sha256": "db4045afe4585120ab298464c37887d8567a0ecadbe8eaa6a0e348c364d745bb" }, "downloads": -1, "filename": "drf-api-checker-0.4.1.tar.gz", "has_sig": false, "md5_digest": "5c9d5804acc8cb6e0e68d7828a17b950", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13343, "upload_time": "2018-09-20T09:27:49", "url": "https://files.pythonhosted.org/packages/12/dd/a93e1a320131eaab94fd9addb56138f7189a0575a8fd57c4b6ecea7b5a46/drf-api-checker-0.4.1.tar.gz" } ], "0.5.1": [ { "comment_text": "", "digests": { "md5": "5a32649420323327f00d1ca7280573ea", "sha256": "c2620623511db916022509061d6f02ac1e95f52c88aeb81e67208ff541f88878" }, "downloads": -1, "filename": "drf-api-checker-0.5.1.tar.gz", "has_sig": false, "md5_digest": "5a32649420323327f00d1ca7280573ea", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13479, "upload_time": "2019-08-16T08:07:33", "url": "https://files.pythonhosted.org/packages/9f/40/96618e8710280efd18b6f2daf3e18bea7b56eaec8bb7bfe9cdbbf2cb7ac6/drf-api-checker-0.5.1.tar.gz" } ], "0.6.0": [ { "comment_text": "", "digests": { "md5": "b9411523cd96247c71d3e5cea0ae3799", "sha256": "77dfdf68b456b495f76ccd597d423a8187854f213848d42e66e0cb3d4912a926" }, "downloads": -1, "filename": "drf-api-checker-0.6.0.tar.gz", "has_sig": false, "md5_digest": "b9411523cd96247c71d3e5cea0ae3799", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13562, "upload_time": "2019-08-16T11:42:30", "url": "https://files.pythonhosted.org/packages/f0/a3/aedab305a3d1c6d6e6397cc27ed12cba9d684a8c8fe70a1a764de33164f5/drf-api-checker-0.6.0.tar.gz" } ], "0.7.0": [ { "comment_text": "", "digests": { "md5": "bdf0bdb04769f4038eb80efda9f2f3a3", "sha256": "606861d85a3f0bfda7b3789a6bc4ed1c92724662d2e0756b5a2bb9841a21d4df" }, "downloads": -1, "filename": "drf-api-checker-0.7.0.tar.gz", "has_sig": false, "md5_digest": "bdf0bdb04769f4038eb80efda9f2f3a3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14481, "upload_time": "2019-08-21T13:14:37", "url": "https://files.pythonhosted.org/packages/76/7d/84d7e9a40e8872aa3f7ec509970aa43e804cbd016523a1b6371f00709503/drf-api-checker-0.7.0.tar.gz" } ], "0.8.0": [ { "comment_text": "", "digests": { "md5": "fc2b62e15bc2f7e2faea1fe130ada1ee", "sha256": "8573b2510e71803900acf11dc259a5ea51e9d773455fd851538a661c2bf9eceb" }, "downloads": -1, "filename": "drf-api-checker-0.8.0.tar.gz", "has_sig": false, "md5_digest": "fc2b62e15bc2f7e2faea1fe130ada1ee", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15399, "upload_time": "2019-09-16T19:09:26", "url": "https://files.pythonhosted.org/packages/c5/ce/f8bb3211b356d2b9505c4b42c7bdbff2e483c5fc1e51fc034fe3a5ecbb89/drf-api-checker-0.8.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "fc2b62e15bc2f7e2faea1fe130ada1ee", "sha256": "8573b2510e71803900acf11dc259a5ea51e9d773455fd851538a661c2bf9eceb" }, "downloads": -1, "filename": "drf-api-checker-0.8.0.tar.gz", "has_sig": false, "md5_digest": "fc2b62e15bc2f7e2faea1fe130ada1ee", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15399, "upload_time": "2019-09-16T19:09:26", "url": "https://files.pythonhosted.org/packages/c5/ce/f8bb3211b356d2b9505c4b42c7bdbff2e483c5fc1e51fc034fe3a5ecbb89/drf-api-checker-0.8.0.tar.gz" } ] }