{ "info": { "author": "Einenlum", "author_email": "yann.rabiller@gmail.com", "bugtrack_url": null, "classifiers": [ "License :: OSI Approved :: MIT License", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3 :: Only", "Topic :: Software Development :: Testing", "Topic :: Software Development :: Testing :: Acceptance", "Topic :: Software Development :: Testing :: BDD", "Topic :: Software Development :: Testing :: Mocking", "Topic :: Software Development :: Testing :: Unit" ], "description": "# Specify\n\nA [PHPSpec](https://github.com/phpspec/phpspec)-like for Python. For fun only (for now). If you're looking for a real valid PHPSpec-like, you could check [flowp](http://pawelgalazka.github.io/flowp/testing.html) (but deprecated). [mamba](https://nestorsalceda.com/mamba/) could also interest you, even if it's not exactly what you are searching.\n\n## Install\n\n`pip install specify`\n\n## Usage\n\nYou can check the [examples](examples) folder.\n\n```python\nfrom specify import ObjectBehavior\nfrom examples.calculator import Calculator\n\nclass CalculatorSpec(ObjectBehavior):\n def _let(self):\n self._describe(Calculator)\n self._be_constructed_with('lorem', id=32)\n\n def it_adds_the_numbers(self):\n self.add(2, 3)._should_be(5)\n```\n\nThe command `python -m specify examples/spec/calculator_spec.py` will render a valid TAP output (hopefully).\n\n```\nTAP version 13\n1..1\n\nok 1 - CalculatorSpec: it adds the numbers\n```\n\nTo have a nice and pretty output, you can then use a TAP formatter like [faucet](https://www.npmjs.com/package/faucet).\n\n- **All specifications must start by `it_`.**\n\n- **All spec files must end by `_spec` for now.**\n\n## Builtin matchers\n\n| Matcher | Details | Alias |\n| --------------------------- | ----------------------- | ------------------------------- |\n| `_should_be` | check with `is` | `_should_return` |\n| `_should_be_like` | check with `==` | `_should_return_like` |\n| `_should_not_be` | check with `is not` | `_should_not_return` |\n| `_should_not_be_like` | check with `!=` | `_should_not_return_like` |\n| `_should_be_an_instance_of` | check with `isinstance` | `_should_return_an_instance_of` |\n| `_should_have_length` | check with `len(x)` | |\n\n## Custom matchers\n\nYou can implement a `_matchers` function in your spec, to add custom matchers.\n\nThe key of the matcher is left trimmed by `_should_` and the first argument\npassed to your function is the value itself.\n\nIf you return false, the test will fail.\n\nHere is an example:\n\n```python\nclass CalculatorSpec(ObjectBehavior):\n # ...\n\n def it_adds_the_numbers(self):\n self.add(2, 3)._should_be_a_number()\n self.add(2, 3)._should_be_greater_than(10)\n\n def _matchers(self):\n def be_a_number(value, *args):\n return isinstance(value, int)\n\n def be_greater_than(value, expected_value):\n return value > expected_value\n\n return {\n 'be_a_number': be_a_number,\n 'be_greater_than': be_greater_than\n }\n```\n\n## Fluent API\n\nAll matchers (builtin and custom) are chainable. Example:\n\n`self.add(2, 3)._should_be_a_number()._should_be(5)._should_be_greater_than(3)`\n\n## Mocks\n\nThanks to [prophepy](https://github.com/Einenlum/prophepy) (did you get the pun with `prophecy`? Hoho), you can\neasily mock things in a [Prophecy](https://github.com/phpspec/prophecy) way.\n\n### Collaborators\n\nGiven this `Displayer` class:\n\n```python\nfrom .calculator import Calculator\n\nclass Displayer:\n def __init__(self, calculator: Calculator):\n self.calculator = calculator\n\n def display_addition(self, *args) -> str:\n total = str(self.calculator.add(*args))\n args = [str(arg) for arg in args]\n\n return f\"{' + '.join(args)} = {total}\"\n```\n\nHere is the spec, mocking the `Calculator`:\n\n```python\nfrom specify import ObjectBehavior, mock\nfrom examples.calculator import Calculator\nfrom examples.displayer import Displayer\n\nclass DisplayerSpec(ObjectBehavior):\n\n @mock(Calculator)\n def _let(self, calculator):\n self._describe(Displayer)\n self._be_constructed_with(calculator)\n self.__calculator = calculator\n\n def it_displays_addition(self):\n self.__calculator.add(2, 3)._should_be_called()\n self.__calculator.add(2, 3)._will_return(5)\n self.display_addition(2, 3)._should_be_like('2 + 3 = 5')\n```\n\nEasy peasy.\n\n### Internal calls to modules\n\n```python\nfrom specify import mock_internal\n\n# ...\n\n@mock_internal('getcwd', lambda : 'loremipsum', from_module='os')\ndef it_displays_addition(self):\n # ...\n # getcwd() will return 'loremipsum' and will be go back to default after\n the test\n```\n\n## TODO\n\n- Handle attributes and not only methods\n- Improve the way interal calls are mocked\n- Make the tap output a stream as the spec say\n- Improve the shitty way specs are loaded for now (maybe use ast like [mamba](https://github.com/nestorsalceda/mamba/blob/8ec25de42171403a3ecf3db4c162053af058f6d7/mamba/example_collector.py#L54)?)\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "", "keywords": "", "license": "MIT", "maintainer": "Einenlum", "maintainer_email": "yann.rabiller@gmail.com", "name": "specify", "package_url": "https://pypi.org/project/specify/", "platform": "", "project_url": "https://pypi.org/project/specify/", "project_urls": null, "release_url": "https://pypi.org/project/specify/0.0.9/", "requires_dist": [ "prophepy (>=0.0.4)" ], "requires_python": ">=3.7,<4.0", "summary": "A spec tool to describe your classes", "version": "0.0.9" }, "last_serial": 4821652, "releases": { "0.0.1": [ { "comment_text": "", "digests": { "md5": "f983ae261c1408f0553ba131096f39c1", "sha256": "c44e75885a524f70bc8d965370796e7050a3f9a5e41c130886d989e294c3be4e" }, "downloads": -1, "filename": "specify-0.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "f983ae261c1408f0553ba131096f39c1", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.7,<4.0", "size": 12906, "upload_time": "2019-02-13T22:47:52", "url": "https://files.pythonhosted.org/packages/f5/ad/ad67f78dce15275ff40749452dca3198af1f9f428439824ed49ffb79f82d/specify-0.0.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "685d281d10ab80f201e2583389b2e3d3", "sha256": "62fc52c62e353db7b7fd7b7c059a898480f678240c8df8adecf1def1a8e80bd1" }, "downloads": -1, "filename": "specify-0.0.1.tar.gz", "has_sig": false, "md5_digest": "685d281d10ab80f201e2583389b2e3d3", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7,<4.0", "size": 4659, "upload_time": "2019-02-13T22:47:54", "url": "https://files.pythonhosted.org/packages/b1/05/0a9b6acb96fefd1757ecdc0e0a6ab93d8f05763f8037fa66652fd9cdc95a/specify-0.0.1.tar.gz" } ], "0.0.2": [ { "comment_text": "", "digests": { "md5": "8b4b076a8b7d67e434f581b36dd6139b", "sha256": "572d48f6e650121fb7174bb8cceefa85b576189e75028076139a71f4daf67dff" }, "downloads": -1, "filename": "specify-0.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "8b4b076a8b7d67e434f581b36dd6139b", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.7,<4.0", "size": 12967, "upload_time": "2019-02-13T23:04:38", "url": "https://files.pythonhosted.org/packages/27/87/298e620b23cdfd5fe9d149810ed2dc27001cc698983413fc64a0f2b82277/specify-0.0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "af843fb08dfc573273c273e14b1d2e13", "sha256": "bf275b4f7706f452ebe74a9417c53b6f23aa332711e390803b7c7fba2566d6c7" }, "downloads": -1, "filename": "specify-0.0.2.tar.gz", "has_sig": false, "md5_digest": "af843fb08dfc573273c273e14b1d2e13", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7,<4.0", "size": 4786, "upload_time": "2019-02-13T23:04:40", "url": "https://files.pythonhosted.org/packages/d9/ce/2b034da05a00a46a413db032350adcc1cee04135c08d37e3f79772bef4ad/specify-0.0.2.tar.gz" } ], "0.0.3": [ { "comment_text": "", "digests": { "md5": "c373601f0576cc4b133a00eabe28a983", "sha256": "a2721c7914382d34280b93270a579151b7bc4188a07e25df90fc1f7f3b9443df" }, "downloads": -1, "filename": "specify-0.0.3-py3-none-any.whl", "has_sig": false, "md5_digest": "c373601f0576cc4b133a00eabe28a983", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.7,<4.0", "size": 14402, "upload_time": "2019-02-13T23:07:07", "url": "https://files.pythonhosted.org/packages/96/e1/94821bd76d0ed53d5d2058c12d9b080b86a39069221f6325cc6d0bd65d17/specify-0.0.3-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "9b8d926a0c2473de17a9df863c72cb01", "sha256": "26d02fad835b136accbb592d31093608c514c81ce76afb3a8bfe55d94cdbb66d" }, "downloads": -1, "filename": "specify-0.0.3.tar.gz", "has_sig": false, "md5_digest": "9b8d926a0c2473de17a9df863c72cb01", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7,<4.0", "size": 6603, "upload_time": "2019-02-13T23:07:08", "url": "https://files.pythonhosted.org/packages/75/d9/133efbb54a71a003408715c239bcbede5fe10700cfa7919233c54f99a3e2/specify-0.0.3.tar.gz" } ], "0.0.4": [ { "comment_text": "", "digests": { "md5": "016957d90bf81b4d2b833b5f88125b19", "sha256": "e3b64f5037776455f828cb4eb2c8e748a4aafca3bc8432b11900439abfbb0389" }, "downloads": -1, "filename": "specify-0.0.4-py3-none-any.whl", "has_sig": false, "md5_digest": "016957d90bf81b4d2b833b5f88125b19", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.7,<4.0", "size": 14655, "upload_time": "2019-02-14T00:08:11", "url": "https://files.pythonhosted.org/packages/8d/7a/1af68966fb5f1f0540bd38cc503eba1fb257f78da4afd80c36b922ceabad/specify-0.0.4-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "756d81a60e12874328cd35af4e6d2f0b", "sha256": "db8470bade75f7c95b63b582032a9c10f8b2d08fb4a583c9a99c2658880564ca" }, "downloads": -1, "filename": "specify-0.0.4.tar.gz", "has_sig": false, "md5_digest": "756d81a60e12874328cd35af4e6d2f0b", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7,<4.0", "size": 7567, "upload_time": "2019-02-14T00:08:12", "url": "https://files.pythonhosted.org/packages/e5/19/843ba16bb421c5ab25fd584c287059092f0b6b7299ecd967bee777a66b8a/specify-0.0.4.tar.gz" } ], "0.0.5": [ { "comment_text": "", "digests": { "md5": "08d2f27a915935b77408711d56625393", "sha256": "955725db5e803db40100757d199a51f4b3e4d3d2d18d76d269c8fb2f3f6eae07" }, "downloads": -1, "filename": "specify-0.0.5-py3-none-any.whl", "has_sig": false, "md5_digest": "08d2f27a915935b77408711d56625393", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.7,<4.0", "size": 14874, "upload_time": "2019-02-14T11:37:16", "url": "https://files.pythonhosted.org/packages/35/1a/82657e16f2e124f7415223c5691a7b947a5f4d010997c6e8e54368ace1fa/specify-0.0.5-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "75780cffcbad4dc2504ca339f0d7374f", "sha256": "82561f2af56e410f9295c0202f054969027fc81774d9557ce57f99d19ff09bb8" }, "downloads": -1, "filename": "specify-0.0.5.tar.gz", "has_sig": false, "md5_digest": "75780cffcbad4dc2504ca339f0d7374f", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7,<4.0", "size": 7788, "upload_time": "2019-02-14T11:37:17", "url": "https://files.pythonhosted.org/packages/5b/3a/5fae126fb10c0de4ef30ca4746df9902d2c6e4f6c11d3ea827add764666f/specify-0.0.5.tar.gz" } ], "0.0.6": [ { "comment_text": "", "digests": { "md5": "c46aa2867d3a559d3511c72b02650f66", "sha256": "ab3568c8cf5dd31f7142359068178afa21b4e8689cf27a1559e8d0e217edc193" }, "downloads": -1, "filename": "specify-0.0.6-py3-none-any.whl", "has_sig": false, "md5_digest": "c46aa2867d3a559d3511c72b02650f66", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.7,<4.0", "size": 15070, "upload_time": "2019-02-14T11:55:48", "url": "https://files.pythonhosted.org/packages/72/55/6876a505b8ef547ba7e9f419aab8243557970dcb96b0357aaac988f97873/specify-0.0.6-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "0c897cd756ef14b9ff26cb23273b275a", "sha256": "19afc2db5d4fc9e71fb0ba77f6f6d7adf7064d11312d21b17a977fc557218a4d" }, "downloads": -1, "filename": "specify-0.0.6.tar.gz", "has_sig": false, "md5_digest": "0c897cd756ef14b9ff26cb23273b275a", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7,<4.0", "size": 7872, "upload_time": "2019-02-14T11:55:50", "url": "https://files.pythonhosted.org/packages/fa/a0/08114cc3f56df25838a8ce31abeec1d0cc2723c583fee3ae0c147f88fc3e/specify-0.0.6.tar.gz" } ], "0.0.7": [ { "comment_text": "", "digests": { "md5": "83b367837922392ddcd64991c9d3b9e9", "sha256": "3a08d4928d6ee7b1eeade5e146eb6c8b5d09cbed37b0ff35ce15f3b5d1dc837b" }, "downloads": -1, "filename": "specify-0.0.7-py3-none-any.whl", "has_sig": false, "md5_digest": "83b367837922392ddcd64991c9d3b9e9", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.7,<4.0", "size": 16246, "upload_time": "2019-02-14T14:53:09", "url": "https://files.pythonhosted.org/packages/94/0d/ec13e018c119e366f98797bfa4c8409c722f9507ca32d4ee427a001a349c/specify-0.0.7-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ee10d3634e79ea17114c9e89b15ace5d", "sha256": "cc08c5d61118035bb22cdc570e4eaef4d9ed98a70555ef83e429bbc6ee195682" }, "downloads": -1, "filename": "specify-0.0.7.tar.gz", "has_sig": false, "md5_digest": "ee10d3634e79ea17114c9e89b15ace5d", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7,<4.0", "size": 8198, "upload_time": "2019-02-14T14:53:10", "url": "https://files.pythonhosted.org/packages/de/88/cea74139bff1a192bff5ec95b007a24f69ce1dcca642d33a6f4d9990c6e5/specify-0.0.7.tar.gz" } ], "0.0.8": [ { "comment_text": "", "digests": { "md5": "19f9d2dd516308595bba5ff5df4114a3", "sha256": "393c2f68bf5f11d7e5020b04714eec492158ca37f17e395ffbe23dd114107e2a" }, "downloads": -1, "filename": "specify-0.0.8-py3-none-any.whl", "has_sig": false, "md5_digest": "19f9d2dd516308595bba5ff5df4114a3", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.7,<4.0", "size": 16329, "upload_time": "2019-02-14T14:56:37", "url": "https://files.pythonhosted.org/packages/eb/fe/478ebf3d822621a2da1f7e19c7cfcbb7fe90c986d5a5946d652ec07de55b/specify-0.0.8-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "8e1bf243d26c762e3fb7fbc05a9fe2fd", "sha256": "74e27b8b979d4875818e2feb8d869717abeea16884b622cd582faf2d622894c0" }, "downloads": -1, "filename": "specify-0.0.8.tar.gz", "has_sig": false, "md5_digest": "8e1bf243d26c762e3fb7fbc05a9fe2fd", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7,<4.0", "size": 8230, "upload_time": "2019-02-14T14:56:39", "url": "https://files.pythonhosted.org/packages/29/5b/222102a7e647bb7b67026d0b5e48089eda4854fa308c6033a30ae8c80d8f/specify-0.0.8.tar.gz" } ], "0.0.9": [ { "comment_text": "", "digests": { "md5": "7f51d6ac70c28dc0f00f020dc07dbfcf", "sha256": "d25c0d689d86b141ed56fdb589a100340f976f42f382345a3c50c0cb1c7c371a" }, "downloads": -1, "filename": "specify-0.0.9-py3-none-any.whl", "has_sig": false, "md5_digest": "7f51d6ac70c28dc0f00f020dc07dbfcf", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.7,<4.0", "size": 17075, "upload_time": "2019-02-14T18:33:47", "url": "https://files.pythonhosted.org/packages/5c/9a/1a97d6c7ae6475a6873d5716bd4be65fe2b5ebb2ba68dacf1b6e0c144d17/specify-0.0.9-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "37428a678d403ce928ea0e663451f51e", "sha256": "57d7a7d452c1fdbf208f4bd37e55eddeab8fb139b46ba491ec2fad04a07285cd" }, "downloads": -1, "filename": "specify-0.0.9.tar.gz", "has_sig": false, "md5_digest": "37428a678d403ce928ea0e663451f51e", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7,<4.0", "size": 8729, "upload_time": "2019-02-14T18:33:48", "url": "https://files.pythonhosted.org/packages/c9/25/4742c9e13c107050dac96ea0759278722064affa992ac7183f07d3338ef5/specify-0.0.9.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "7f51d6ac70c28dc0f00f020dc07dbfcf", "sha256": "d25c0d689d86b141ed56fdb589a100340f976f42f382345a3c50c0cb1c7c371a" }, "downloads": -1, "filename": "specify-0.0.9-py3-none-any.whl", "has_sig": false, "md5_digest": "7f51d6ac70c28dc0f00f020dc07dbfcf", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.7,<4.0", "size": 17075, "upload_time": "2019-02-14T18:33:47", "url": "https://files.pythonhosted.org/packages/5c/9a/1a97d6c7ae6475a6873d5716bd4be65fe2b5ebb2ba68dacf1b6e0c144d17/specify-0.0.9-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "37428a678d403ce928ea0e663451f51e", "sha256": "57d7a7d452c1fdbf208f4bd37e55eddeab8fb139b46ba491ec2fad04a07285cd" }, "downloads": -1, "filename": "specify-0.0.9.tar.gz", "has_sig": false, "md5_digest": "37428a678d403ce928ea0e663451f51e", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7,<4.0", "size": 8729, "upload_time": "2019-02-14T18:33:48", "url": "https://files.pythonhosted.org/packages/c9/25/4742c9e13c107050dac96ea0759278722064affa992ac7183f07d3338ef5/specify-0.0.9.tar.gz" } ] }