{ "info": { "author": "Jeff Hui", "author_email": "contrib@jeffhui.net", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Topic :: Software Development :: Libraries", "Topic :: Software Development :: Testing" ], "description": "Describe\n========\n\nA `Behavior Driven Development`_ or BDD framework inspired off of RSpec_. The reason of BDD over\nTDD is out of scope of this project. But this framework is simply a way to try and\nencourage me to do more testing.\n\nIt is worth noting the `development version`_ breaks the existing API.\n\n.. _Behavior Driven Development: http://en.wikipedia.org/wiki/Behavior_Driven_Development\n.. _BDD: http://en.wikipedia.org/wiki/Behavior_Driven_Development\n.. _RSpec: http://rspec.info/\n.. _development version: https://github.com/jeffh/describe/tarball/dev#egg=describe-dev\n\nInstallation\n-------------\n\nTo install, use pip or easy_install::\n\n pip install describe\n\nThen you can import it::\n\n from describe import Spec, Value, Mock # classes\n from describe import arg, repository # submodules\n\nUsage\n=====\n\nQuickstart\n-----------\n\nThen you can import the library for use in unittest or nose. The core feature is the Value object::\n\n from describe import Value\n\nUse this Value class to wrap values you want to set expectations. Here's some API\nexamples until I get proper documentation::\n\n # self.assertEquals(9, 9)\n Value(9).should == 9\n\n # self.assertAlmostEqual(5.0-4.0, 1.0)\n Value(5.0-4.0).should.be_close_to(1.0)\n\n # self.assertIn(3, (2,3,4))\n Value((2,3,4)).should.contain(3)\n\n # self.assertNotIn(5, (2,3,4))\n Value((2,3,4)).should_not.contain(5)\n\n # self.assertFalse(False)\n Value(False).should.be.false()\n\n # self.assertTrue(isinstance((), tuple))\n Value(()).should.be.instance_of(tuple)\n\n # self.assertEqual(len(range(5)), 5)\n # '.elements' is optional\n Value(range(5)).should.have(5).elements\n\n # self.assertGreaterEqual(len(range(5)), 4)\n Value(range(5)).should.have.at_least(4)\n\nMocks\n-----\n\nMocks are used to abstract out classes that are not being tested. They can customized to return\nspecific results and logs all operations done to it for verification later on. The mock API wraps\nthe `voidspace mock library`_. Feel free to use it directly instead of this API.\n\ndescribe.Mock supports a few operations:\n\n* ``Mock.should_access property`` - Allows you to set expectations of method calls and attribute accesses.\n* ``Mock.should_not_access(attr_name)`` - Allows you to set expections of attributes not getting accessed.\n* ``Mock.verify()`` - Verifies all the expectations, throwing AssertionErrors if need be.\n* ``Mock.reset_mock()`` - clears the access log, you should never really use this directly.\n\nAll other attributes get directed to the `voidspace mock object`_. A basic example::\n\n # create the mock\n from describe import Mock\n m = Mock()\n\n # set an expectation on what will be performed on the object and it's response\n m.should_access.upper().and_return('FOO')\n\n # run it\n m.upper() # => 'FOO'\n\n # verify that the operations were executed\n m.verify()\n\n # if you want to invoke any operations on the mock object (and not the API), get the\n # voidspace mock object via the mock attribute:\n m.should_access.verify().and_return('bar')\n m.mock.verify() # => 'bar'\n m.verify()\n\nThese expectations expect the function prototype you give it::\n\n m.should_access.rjust(5).and_return(' ')\n m.rjust() # => None - prototype does not match.\n m.rjust(5) # => ' '\n m.verify() # will raise AssertionError because m.rjust() was called\n\nKeyword arguments work just as well as args. There are several special arguments you can give\nfor special operations.\n\nargs.ANYTHING accepts any arguments as valid, including no arguments::\n\n from describe import args\n m.should_access.rjust(args.ANYTHING).and_return('anything works')\n m.rjust('foo', 'bar') # => 'anything works'\n\nargs.ANY_ARG accepts any single argument::\n\n from describe import args\n m.should_access.rjust(args.ANY_ARG).and_return(4)\n m.rjust() # => None - is not one argument\n m.rjust(3) # => 4\n\nOther special args include:\n\n* ``arg.ARGS`` - any non-keyword arguments\n* ``arg.KWARGS`` - any keyworded arguments\n* ``arg.an_instance_of(type)`` - any argument whos value matches the given type\n* ``arg.regexp`` - alias for arg.an_instance_of(type(re.compile(''))) for a regular expression type.\n* ``arg.includes_pair(key, value)`` - any argument who has a key and associated value.\n* ``arg.contains(item, *items)`` - any keys or items in the given list or dictionary.\n* ``arg.duck_type(*attributes)`` - any object that has all of the given attributes\n\nYou can also set expectations for getter properties::\n\n m.should_access.score.and_return(23)\n m.score # => 23\n\nCalling verify on every mock object you create is tiresome. Fortunately, each mock is added to\na registry when instantiated. By default, they are added to the describe.mock.repository.default\nrepository. You can call verify() on the repository to verify all mocks in it::\n\n # create mocks:\n from describe import Mock, Value\n from describe.mock import repository\n for i in range(5):\n m = Mock()\n m.should_access.lower().and_return('bar')\n Value(m.lower()).should == 'bar'\n\n repository.default.verify() # will verify all mock objects we created above\n\n.. _voidspace mock library: http://www.voidspace.org.uk/python/mock/\n.. _voidspace mock object: http://www.voidspace.org.uk/python/mock/mock.html\n\nSpecs\n-----\n\nThe entire purpose of behavior driven development, is to remap the testing-based terminology to\nmore specification driven ones. The Spec class is an alternative to unittest.TestCase, but you'll\nneed nose_ / sniffer_ to reap all the benefits.\n\nCurrently Specs inherit unittest.TestCase::\n\n from describe import Spec, Mock\n from describ.args import *\n class DescribeRSpecExpectingArguments(Spec):\n def before(self):\n self.m = Mock()\n\n def it_should_expect_arguments(self):\n self.m.should_access.msg(1,2,3)\n self.m.msg(1,2,3)\n\n def it_should_expect_arguments_with_count(self):\n self.m.should_access.msg(1,2,3).once\n self.m.msg(1,2,3)\n\n def it_should_expect_no_arguments(self):\n self.m.should_access.msg()\n self.m.msg()\n\n def it_should_expect_any_arguments(self):\n self.m.should_access.msg(ANYTHING)\n self.m.msg(1,2,3,4,5,6)\n\nThen use the `SpecPlugin`` for nose to run the specs, or run describe.main program.\n\n.. _nose: http://somethingaboutorange.com/mrl/projects/nose/1.0.0/\n.. _sniffer: https://github.com/jeffh/sniffer", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://github.com/jeffh/describe/", "keywords": null, "license": "MIT", "maintainer": null, "maintainer_email": null, "name": "describe", "package_url": "https://pypi.org/project/describe/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/describe/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://github.com/jeffh/describe/" }, "release_url": "https://pypi.org/project/describe/0.1.2/", "requires_dist": null, "requires_python": null, "summary": "An experimental behavioral framework inspired from rspec.", "version": "0.1.2" }, "last_serial": 371028, "releases": { "0.1.1": [ { "comment_text": "", "digests": { "md5": "8d4d5aabbafa4bcec08f68e6ae9f3632", "sha256": "2a7a3be1b557770b4b463f5b4e6a1d1e1bd29f323cc0f12c05ae80adfcec1e87" }, "downloads": -1, "filename": "describe-0.1.1.tar.gz", "has_sig": false, "md5_digest": "8d4d5aabbafa4bcec08f68e6ae9f3632", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10524, "upload_time": "2010-12-22T21:36:43", "url": "https://files.pythonhosted.org/packages/e9/3f/5af7dd90b27f0d58821e7264eb4db9579684ce5514f4897881800b1200ec/describe-0.1.1.tar.gz" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "0fc87accce46c5d184ac8d30f4426286", "sha256": "a75f6206f57fd07352cd7b47bf40ae9ae557d682457802369700a71ec73e9a76" }, "downloads": -1, "filename": "describe-0.1.2.tar.gz", "has_sig": false, "md5_digest": "0fc87accce46c5d184ac8d30f4426286", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 27491, "upload_time": "2012-02-01T05:01:07", "url": "https://files.pythonhosted.org/packages/20/e8/94fd753cd26bb30e4c2a7de8f3aabb6b7b2c57c352470af25cd19cd42ea3/describe-0.1.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "0fc87accce46c5d184ac8d30f4426286", "sha256": "a75f6206f57fd07352cd7b47bf40ae9ae557d682457802369700a71ec73e9a76" }, "downloads": -1, "filename": "describe-0.1.2.tar.gz", "has_sig": false, "md5_digest": "0fc87accce46c5d184ac8d30f4426286", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 27491, "upload_time": "2012-02-01T05:01:07", "url": "https://files.pythonhosted.org/packages/20/e8/94fd753cd26bb30e4c2a7de8f3aabb6b7b2c57c352470af25cd19cd42ea3/describe-0.1.2.tar.gz" } ] }