{ "info": { "author": "Jefferson Heard", "author_email": "jheard@teamworks.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.2", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Topic :: Software Development :: Testing" ], "description": "# Dustbunny\n\n* **Author:** Jefferson Heard \n* **Version:** 0.0.1\n\n## Introduction\n\nDustbunny creates fuzz records for SQL databases. It's based on [Hypothesis](http://hypothesis.works/) and uses it to \ngenerate random values for data columns. The difference between using Dustbunny vs. Hypothesis directly is that it's \neasier to generate values that are relative to an already generated value, and it's easier to structure the generation \nof relationships between tables, such as foreign keys. \n\nDustbunny also records the records it generates, so you can remove them from the database when you \nare done with them.\n\n## Working with Dustbunny\n\n1. Create a Generate instance with the sqla session and ORM model that you want to generate.\n2. Change the creation function (will use the default model create if you don't)\n3. Set the number of records you want to generate total \n4. Set-up parent records using `for_some` or `for all`\n4. Set fixed and random values\n5. Set relative value functions\n6. Call the `.execute()` function\n7. Commit to the database. Generally your creation function should just create, not commit, for the sake of speed.\n\n\n## Example:\n\nThe following generates a random set of appointments with start times distributed throughout the day, and with amounts \nof time distributed between even increments of fifteen minutes, across a predetermined sample of attendees (defined \nelsewhere), and across a predetermined sample of dates. It builds 50 records using the model's controller class \nattribute to create the record. It exercises the facility for generating fixed values, random values from strategies,\n and relative values based on the previous two:\n\n```python\nfrom app.extensions import db\nimport importlib\nfrom hypothesis import strategies as st, settings, given\nfrom dustbunny.hyp.strategies import *\nfrom dustbunny import Generate\nfrom dustbunny.hyp.strategies import gfywords, gfycodes, words\n\nimport_upon_configure(db.Model, here)\n\n# ...\n# initialize the database ...\n# ...\n\nuse_controller = lambda M, **kwargs: M.controller_class.create(_commit=False, **kwargs)\n\n# ... do stuff ,,,\n\n# Grab some initial records we're goin gto use in our fixed values\norg = Org.query.first()\nappointment_type = AppointmentType.query.first()\n\ngen = Generate(db, Appointment)\\\n .by_method(use_controller)\\ # this is called instead of create\n .num(50)\\ # generate 50 records\n .with_fixed_values_for( # use fixed values for the following record attributes\n calendar_sync_google=False, \n is_private=False,\n is_all_day=False,\n enable_notifications=False,\n organization=org,\n appointment_type_id=appointment_type.pk,\n ).using( # use hypothesis strategies for generating the following attributes\n appointment_registration_type_id=st.sampled_from([x.pk for x in AppointmentRegistrationType.query.all()]),\n title=gfywords(), # a dustbunny strategy for generating adj-adj-noun triplets that are unique\n location=gfywords(),\n appt_date=st.sampled_from(date_range),\n notes=words(), # generate random words\n wage_minutes=st.sampled_from((15, 30, 45, 60, 90)),\n wage_code_id=st.sampled_from([x.pk for x in WageCode.query.all()]),\n members = st.lists(st.sampled_from(workers), average_size=5, min_size=1, max_size=25)\n ).with_relative_values_for(\n start_hour=lambda **k: k['appt_date'].hour,\n end_hour=lambda **k: (k['appt_date'] + timedelta(minutes=k['wage_minutes'])).hour,\n start_minute=lambda **k: k['appt_date'].minute,\n end_minute=lambda **k: (k['appt_date'] + timedelta(minutes=k['wage_minutes'])).minute,\n wage_start_hour=lambda **k: k['appt_date'].hour,\n wage_end_hour=lambda **k: (k['appt_date'] + timedelta(minutes=k['wage_minutes'])).hour,\n wage_start_minute=lambda **k: k['appt_date'].minute,\n wage_end_minute=lambda **k: (k['appt_date'] + timedelta(minutes=k['wage_minutes'])).minute,\n is_mandatory=lambda **k: k['wage_minutes'] > 0,\n start_date=lambda **k: k['appt_date'],\n end_date=lambda **k: k['appt_date'] + timedelta(minutes=k['wage_minutes']),\n )\n \nworker_appointments.extend(gen.execute()) # actually create the records\n\ndb.session.commit() # we don't commit during the generation because it takes forever.\n```\n\nA second example, using `for_every` to run the generator once for every parent:\n\n```python\ndb = # ... the orm instance\nLog = # ... a db model.\nuse_controller = # ... a function.\ngen = Generate(db, Log)\\\n .by_method(use_controller)\\\n .num(n=1)\\\n .for_every( # for each permutation of\n ('config', Config.query.all()), # every TmpActivityLogConfig record that exists\n ('log_start_date', date_range) # for 52 weeks\n ).with_fixed_values_for( # set these attributes of the record to fixed values\n log_stage_seq=0,\n log_review_date=None\n ).with_relative_values_for( # set these attributes of the record to values based on everything that came before\n log_end_date=lambda **kwargs: kwargs['log_start_date'] + timedelta(days=7) # make the end date 1 week after the given config\n )\n \nlogs = gen.execute() # execute the insert\n```", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/Teamworksapp/dustbunny", "keywords": "pytest hypothesis sqlalchemy", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "dustbunny", "package_url": "https://pypi.org/project/dustbunny/", "platform": "", "project_url": "https://pypi.org/project/dustbunny/", "project_urls": { "Homepage": "https://github.com/Teamworksapp/dustbunny" }, "release_url": "https://pypi.org/project/dustbunny/1.3.1/", "requires_dist": null, "requires_python": "", "summary": "Generate database records for fuzz testing using SQLAlchemy", "version": "1.3.1" }, "last_serial": 3246046, "releases": { "1.3.0": [ { "comment_text": "", "digests": { "md5": "e1b31787c9fbbdc2f89f46eedbd61be3", "sha256": "3548dd7ede48ae19d53e1aae985d1faf20314752862a5d5a65cc8c85a22b64ff" }, "downloads": -1, "filename": "dustbunny-1.3.0.macosx-10.12-x86_64.tar.gz", "has_sig": false, "md5_digest": "e1b31787c9fbbdc2f89f46eedbd61be3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 42497, "upload_time": "2017-10-12T19:25:19", "url": "https://files.pythonhosted.org/packages/71/ba/c521b7c3d57f9d35051219c34b0b1a304ed3ad1f7755c850359d81ddbb46/dustbunny-1.3.0.macosx-10.12-x86_64.tar.gz" }, { "comment_text": "", "digests": { "md5": "742bb027da73a93fd78c20243e7f10f5", "sha256": "b160dbe0cfdc30b7f65f88195718fc3b563418f783b78536b1310ae59ab45e43" }, "downloads": -1, "filename": "dustbunny-1.3.0-py3.6.egg", "has_sig": false, "md5_digest": "742bb027da73a93fd78c20243e7f10f5", "packagetype": "bdist_egg", "python_version": "3.6", "requires_python": null, "size": 39519, "upload_time": "2017-10-12T19:25:17", "url": "https://files.pythonhosted.org/packages/8d/4a/5f4a34667dbbcf1ec36c001bf0d1f9f7a808acfb6d83d03b23d0b5e424af/dustbunny-1.3.0-py3.6.egg" } ], "1.3.1": [ { "comment_text": "", "digests": { "md5": "997d22ae6b635d502d8b2a2453293d04", "sha256": "9d0c6565732568fac2476d2e0e6e14137beec3db944b7a8033928eca730d2b7c" }, "downloads": -1, "filename": "dustbunny-1.3.1.macosx-10.12-x86_64.tar.gz", "has_sig": false, "md5_digest": "997d22ae6b635d502d8b2a2453293d04", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 42493, "upload_time": "2017-10-12T19:26:46", "url": "https://files.pythonhosted.org/packages/4a/9c/90b47967a3a3377ecc69ecc1fc30604814edfdc497c8b1845a121baf98f8/dustbunny-1.3.1.macosx-10.12-x86_64.tar.gz" }, { "comment_text": "", "digests": { "md5": "a3294cba337aa82ea55d9acf3a62f511", "sha256": "95d882fd8a37a3315bd5facbe3f177a512ac1ed75e78777349163a85f264ee15" }, "downloads": -1, "filename": "dustbunny-1.3.1-py3-none-any.whl", "has_sig": false, "md5_digest": "a3294cba337aa82ea55d9acf3a62f511", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 38499, "upload_time": "2017-10-12T19:29:15", "url": "https://files.pythonhosted.org/packages/f6/79/f6cdb7ce895be72e87bd907cbda7dc56ec848f6721bc4c5b952c10fa4372/dustbunny-1.3.1-py3-none-any.whl" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "997d22ae6b635d502d8b2a2453293d04", "sha256": "9d0c6565732568fac2476d2e0e6e14137beec3db944b7a8033928eca730d2b7c" }, "downloads": -1, "filename": "dustbunny-1.3.1.macosx-10.12-x86_64.tar.gz", "has_sig": false, "md5_digest": "997d22ae6b635d502d8b2a2453293d04", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 42493, "upload_time": "2017-10-12T19:26:46", "url": "https://files.pythonhosted.org/packages/4a/9c/90b47967a3a3377ecc69ecc1fc30604814edfdc497c8b1845a121baf98f8/dustbunny-1.3.1.macosx-10.12-x86_64.tar.gz" }, { "comment_text": "", "digests": { "md5": "a3294cba337aa82ea55d9acf3a62f511", "sha256": "95d882fd8a37a3315bd5facbe3f177a512ac1ed75e78777349163a85f264ee15" }, "downloads": -1, "filename": "dustbunny-1.3.1-py3-none-any.whl", "has_sig": false, "md5_digest": "a3294cba337aa82ea55d9acf3a62f511", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 38499, "upload_time": "2017-10-12T19:29:15", "url": "https://files.pythonhosted.org/packages/f6/79/f6cdb7ce895be72e87bd907cbda7dc56ec848f6721bc4c5b952c10fa4372/dustbunny-1.3.1-py3-none-any.whl" } ] }