sqlalchemy-model-factory


Namesqlalchemy-model-factory JSON
Version 0.4.6 PyPI version JSON
download
home_pagehttps://github.com/dancardin/sqlalchemy-model-factory
SummaryA library to assist in generating models from a central location.
upload_time2023-04-19 14:26:32
maintainer
docs_urlNone
authorDan Cardin
requires_python>=3.6.2,<4
licenseApache-2.0
keywords sqlalchemy model factory pytest
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            [![Actions Status](https://github.com/dancardin/sqlalchemy-model-factory/workflows/build/badge.svg)](https://github.com/dancardin/sqlalchemy-model-factory/actions) [![codecov](https://codecov.io/gh/DanCardin/sqlalchemy-model-factory/branch/main/graph/badge.svg)](https://codecov.io/gh/DanCardin/sqlalchemy-model-factory) [![Documentation Status](https://readthedocs.org/projects/sqlalchemy-model-factory/badge/?version=latest)](https://sqlalchemy-model-factory.readthedocs.io/en/latest/?badge=latest)

sqlalchemy-model-factory aims to make it easy to write factory functions for sqlalchemy
models, particularly for use in testing.

It should make it easy to define as many factories as you might want, with as little
boilerplate as possible, while remaining as unopinionated as possible about the behavior
going in your factories.

## Installation

```python
pip install sqlalchemy-model-factory
```

## Usage

Suppose you've defined a `Widget` model, and for example you want to test some API code
that queries for `Widget` instances. Couple of factory functions might look like so:

```python
# tests/test_example_which_uses_pytest
from sqlalchemy_model_factory import autoincrement, register_at
from . import models

@register_at('widget')
def new_widget(name, weight, color, size, **etc):
    """My goal is to allow you to specify *all* the options a widget might require.
    """
    return Widget(name, weight, color, size, **etc)

@register_at('widget', name='default')
@autoincrement
def new_default_widget(autoincrement=1):
    """My goal is to give you a widget with as little input as possible.
    """
    # I'm gonna call the other factory function...because i can!
    return new_widget(
        f'default_name{autoincrement}',
        weight=autoincrement,
        color='rgb({0}, {0}, {0})'.format(autoincrement),
        size=autoincrement,
    )
```

What this does, is register those functions to the registry of factory functions, within
the "widget" namespace, at the `name` (defaults to `new`) location in the namespace.

So when I go to write a test, all I need to do is accept the `mf` fixture (and lets say
a `session` db connection fixture to make assertions against) and I can call all the
factories that have been registered.

```python
def test_example_model(mf, session):
    widget1 = mf.widget.new('name', 1, 'rgb(0, 0, 0)', 1)
    widget2 = mf.widget.default()
    widget3 = mf.widget.default()
    widget4 = mf.widget.default()

    widgets = session.query(Widget).all()
    assert len(widgets) == 4
    assert widgets[0].name == 'name'
    assert widgets[1].id == widget2.id
    assert widgets[2].name == widget3.name
    assert widgets[3].color == 'rgb(3, 3, 3)'
```

In a simple toy example, where you don't gain much on the calls themselves the benefits
are primarily:

- The instances are automatically put into the database and cleaned up after the test.
- You can make assertions without hardcoding the values, because you get back a handle on the object.

But as the graph of models required to set up a particular scenario grows:

- You can define factories as complex as you want
  - They can create related objects and assign them to relationships
  - They can be given sources of randomness or uniqueness to not violate constraints
  - They can compose with eachother (when called normally, they're the same as the original function).

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/dancardin/sqlalchemy-model-factory",
    "name": "sqlalchemy-model-factory",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.6.2,<4",
    "maintainer_email": "",
    "keywords": "sqlalchemy,model,factory,pytest",
    "author": "Dan Cardin",
    "author_email": "ddcardin@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/4c/c5/dbca8f81db86ee657632e647519f80b0b77ff0ceae65d6b9155bb8b4984f/sqlalchemy-model-factory-0.4.6.tar.gz",
    "platform": null,
    "description": "[![Actions Status](https://github.com/dancardin/sqlalchemy-model-factory/workflows/build/badge.svg)](https://github.com/dancardin/sqlalchemy-model-factory/actions) [![codecov](https://codecov.io/gh/DanCardin/sqlalchemy-model-factory/branch/main/graph/badge.svg)](https://codecov.io/gh/DanCardin/sqlalchemy-model-factory) [![Documentation Status](https://readthedocs.org/projects/sqlalchemy-model-factory/badge/?version=latest)](https://sqlalchemy-model-factory.readthedocs.io/en/latest/?badge=latest)\n\nsqlalchemy-model-factory aims to make it easy to write factory functions for sqlalchemy\nmodels, particularly for use in testing.\n\nIt should make it easy to define as many factories as you might want, with as little\nboilerplate as possible, while remaining as unopinionated as possible about the behavior\ngoing in your factories.\n\n## Installation\n\n```python\npip install sqlalchemy-model-factory\n```\n\n## Usage\n\nSuppose you've defined a `Widget` model, and for example you want to test some API code\nthat queries for `Widget` instances. Couple of factory functions might look like so:\n\n```python\n# tests/test_example_which_uses_pytest\nfrom sqlalchemy_model_factory import autoincrement, register_at\nfrom . import models\n\n@register_at('widget')\ndef new_widget(name, weight, color, size, **etc):\n    \"\"\"My goal is to allow you to specify *all* the options a widget might require.\n    \"\"\"\n    return Widget(name, weight, color, size, **etc)\n\n@register_at('widget', name='default')\n@autoincrement\ndef new_default_widget(autoincrement=1):\n    \"\"\"My goal is to give you a widget with as little input as possible.\n    \"\"\"\n    # I'm gonna call the other factory function...because i can!\n    return new_widget(\n        f'default_name{autoincrement}',\n        weight=autoincrement,\n        color='rgb({0}, {0}, {0})'.format(autoincrement),\n        size=autoincrement,\n    )\n```\n\nWhat this does, is register those functions to the registry of factory functions, within\nthe \"widget\" namespace, at the `name` (defaults to `new`) location in the namespace.\n\nSo when I go to write a test, all I need to do is accept the `mf` fixture (and lets say\na `session` db connection fixture to make assertions against) and I can call all the\nfactories that have been registered.\n\n```python\ndef test_example_model(mf, session):\n    widget1 = mf.widget.new('name', 1, 'rgb(0, 0, 0)', 1)\n    widget2 = mf.widget.default()\n    widget3 = mf.widget.default()\n    widget4 = mf.widget.default()\n\n    widgets = session.query(Widget).all()\n    assert len(widgets) == 4\n    assert widgets[0].name == 'name'\n    assert widgets[1].id == widget2.id\n    assert widgets[2].name == widget3.name\n    assert widgets[3].color == 'rgb(3, 3, 3)'\n```\n\nIn a simple toy example, where you don't gain much on the calls themselves the benefits\nare primarily:\n\n- The instances are automatically put into the database and cleaned up after the test.\n- You can make assertions without hardcoding the values, because you get back a handle on the object.\n\nBut as the graph of models required to set up a particular scenario grows:\n\n- You can define factories as complex as you want\n  - They can create related objects and assign them to relationships\n  - They can be given sources of randomness or uniqueness to not violate constraints\n  - They can compose with eachother (when called normally, they're the same as the original function).\n",
    "bugtrack_url": null,
    "license": "Apache-2.0",
    "summary": "A library to assist in generating models from a central location.",
    "version": "0.4.6",
    "split_keywords": [
        "sqlalchemy",
        "model",
        "factory",
        "pytest"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "0a0b2e5b643e16fe2ad6e816d5cc94f11fde521146c59728cd1a6c3d28a10eb0",
                "md5": "769f86444734ae9ad07aa996fffb450c",
                "sha256": "ae84e15c5f53897d834c17c3d2d6491d29f60914a4f63ea5f7557e4079676d7f"
            },
            "downloads": -1,
            "filename": "sqlalchemy_model_factory-0.4.6-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "769f86444734ae9ad07aa996fffb450c",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.6.2,<4",
            "size": 18072,
            "upload_time": "2023-04-19T14:26:34",
            "upload_time_iso_8601": "2023-04-19T14:26:34.178276Z",
            "url": "https://files.pythonhosted.org/packages/0a/0b/2e5b643e16fe2ad6e816d5cc94f11fde521146c59728cd1a6c3d28a10eb0/sqlalchemy_model_factory-0.4.6-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "4cc5dbca8f81db86ee657632e647519f80b0b77ff0ceae65d6b9155bb8b4984f",
                "md5": "bc3571800862bbb8ecabc7f8ea835bbc",
                "sha256": "195ad9169867b447b528142b506db6489a5d9ab98104e557b28c2d4af8f581ac"
            },
            "downloads": -1,
            "filename": "sqlalchemy-model-factory-0.4.6.tar.gz",
            "has_sig": false,
            "md5_digest": "bc3571800862bbb8ecabc7f8ea835bbc",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.6.2,<4",
            "size": 15410,
            "upload_time": "2023-04-19T14:26:32",
            "upload_time_iso_8601": "2023-04-19T14:26:32.544665Z",
            "url": "https://files.pythonhosted.org/packages/4c/c5/dbca8f81db86ee657632e647519f80b0b77ff0ceae65d6b9155bb8b4984f/sqlalchemy-model-factory-0.4.6.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-04-19 14:26:32",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "github_user": "dancardin",
    "github_project": "sqlalchemy-model-factory",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "sqlalchemy-model-factory"
}
        
Elapsed time: 2.12677s