django-capture-on-commit-callbacks


Namedjango-capture-on-commit-callbacks JSON
Version 1.11.0 PyPI version JSON
download
home_pagehttps://github.com/adamchainz/django-capture-on-commit-callbacks
SummaryCapture and make assertions on transaction.on_commit() callbacks.
upload_time2022-05-10 12:22:53
maintainer
docs_urlNone
authorAdam Johnson
requires_python>=3.7
licenseMIT
keywords django
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            ==================================
django-capture-on-commit-callbacks
==================================

.. image:: https://img.shields.io/github/workflow/status/adamchainz/django-capture-on-commit-callbacks/CI/main?style=for-the-badge
   :target: https://github.com/adamchainz/django-capture-on-commit-callbacks/actions?workflow=CI

.. image:: https://img.shields.io/badge/Coverage-100%25-success?style=for-the-badge
   :target: https://github.com/adamchainz/django-capture-on-commit-callbacks/actions?workflow=CI

.. image:: https://img.shields.io/pypi/v/django-capture-on-commit-callbacks.svg?style=for-the-badge
   :target: https://pypi.org/project/django-capture-on-commit-callbacks/

.. image:: https://img.shields.io/badge/code%20style-black-000000.svg?style=for-the-badge
   :target: https://github.com/psf/black

.. image:: https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white&style=for-the-badge
   :target: https://github.com/pre-commit/pre-commit
   :alt: pre-commit

Capture and make assertions on ``transaction.on_commit()`` `callbacks <https://docs.djangoproject.com/en/3.0/topics/db/transactions/#performing-actions-after-commit>`__.
This allows you to write your tests with the ``TestCase``, rather than needing the slower ``TransactionTestCase`` to actually commit the transactions.

This package was made as a first pass for `Django PR #12944 <https://github.com/django/django/pull/12944>`__, which is a solution for `Ticket #30457 “on_commit should be triggered in a TestCase” <https://code.djangoproject.com/ticket/30457>`__.
The PR has been merged to Django and has been released in version 3.2, so this package can now be considered a backport.

Read more in my blog post `The Fast Way to Test Django transaction.on_commit() Callbacks <https://adamj.eu/tech/2020/05/20/the-fast-way-to-test-django-transaction-on-commit-callbacks/>`__.

Installation
============

Use **pip**:

.. code-block:: bash

    python -m pip install django-capture-on-commit-callbacks

Requirements
============

Python 3.7 to 3.10 supported.

Django 3.2 to 4.0 supported.

**Note:** This package is not needed on Django 4.0+ and it will error on usage for such versions.

----

**Are your tests slow?**
Check out my book `Speed Up Your Django Tests <https://adamchainz.gumroad.com/l/suydt>`__ which covers loads of ways to write faster, more accurate tests.

----

API
===

``capture_on_commit_callbacks(*, using="default", execute=False)``
------------------------------------------------------------------

Acts as a context manager that captures ``on_commit`` callbacks for the given database connection.
It returns a list that contains, on exit of the context, the captured callback functions.
From this list you can make assertions on the callbacks or call them to invoke their side effects, emulating a commit.

All arguments must be passed as keyword arguments.

``using`` is the alias of the database connection to capture callbacks for.

``execute`` specifies whether to call all the callbacks automatically as the context manager exits, if no exception has been raised.

For example, you can test a commit hook that sends an email like so:

.. code-block:: python

    from django.core import mail
    from django.test import TestCase
    from django_capture_on_commit_callbacks import capture_on_commit_callbacks


    class ContactTests(TestCase):
        def test_post(self):
            with capture_on_commit_callbacks() as callbacks:
                response = self.client.post(
                    "/contact/",
                    {"message": "I like your site"},
                )

            self.assertEqual(response.status_code, 200)

            self.assertEqual(len(callbacks), 1)
            # Execute the callback
            callbacks[0]()

            self.assertEqual(len(mail.outbox), 1)
            self.assertEqual(mail.outbox[0].subject, "Contact Form")
            self.assertEqual(mail.outbox[0].body, "I like your site")

The same test can be written a bit more succinctly with ``execute=True``:

.. code-block:: python

    from django.core import mail
    from django.test import TestCase
    from django_capture_on_commit_callbacks import capture_on_commit_callbacks


    class ContactTests(TestCase):
        def test_post(self):
            with capture_on_commit_callbacks(execute=True) as callbacks:
                response = self.client.post(
                    "/contact/",
                    {"message": "I like your site"},
                )

            self.assertEqual(response.status_code, 200)

            self.assertEqual(len(callbacks), 1)

            self.assertEqual(len(mail.outbox), 1)
            self.assertEqual(mail.outbox[0].subject, "Contact Form")
            self.assertEqual(mail.outbox[0].body, "I like your site")

``TestCaseMixin``
-----------------

A mixin class to be added to your custom ``TestCase`` subclass.
It adds one method, ``captureOnCommitCallbacks()`` that aliases ``capture_on_commit_callbacks()``, to match the ``camelCase`` style of unittest assertions.

You can add to your custom ``TestCase`` classes like so:

.. code-block:: python

    from django import test
    from django_capture_on_commit_callbacks import TestCaseMixin


    class TestCase(TestCaseMixin, test.TestCase):
        pass

You could then rewrite the above tests with your custom ``TestCase`` class like so:

.. code-block:: python

    from django.core import mail
    from example.test import TestCase


    class ContactTests(TestCase):
        def test_post(self):
            with self.captureOnCommitCallbacks(execute=True) as callbacks:
                response = self.client.post(
                    "/contact/",
                    {"message": "I like your site"},
                )

            self.assertEqual(response.status_code, 200)

            self.assertEqual(len(callbacks), 1)

            self.assertEqual(len(mail.outbox), 1)
            self.assertEqual(mail.outbox[0].subject, "Contact Form")
            self.assertEqual(mail.outbox[0].body, "I like your site")



            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/adamchainz/django-capture-on-commit-callbacks",
    "name": "django-capture-on-commit-callbacks",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.7",
    "maintainer_email": "",
    "keywords": "Django",
    "author": "Adam Johnson",
    "author_email": "me@adamj.eu",
    "download_url": "https://files.pythonhosted.org/packages/64/b4/b6cd102b08e82b8020896619cbf0df2ade14b17edb7e4a0c5188f2da0a60/django-capture-on-commit-callbacks-1.11.0.tar.gz",
    "platform": null,
    "description": "==================================\ndjango-capture-on-commit-callbacks\n==================================\n\n.. image:: https://img.shields.io/github/workflow/status/adamchainz/django-capture-on-commit-callbacks/CI/main?style=for-the-badge\n   :target: https://github.com/adamchainz/django-capture-on-commit-callbacks/actions?workflow=CI\n\n.. image:: https://img.shields.io/badge/Coverage-100%25-success?style=for-the-badge\n   :target: https://github.com/adamchainz/django-capture-on-commit-callbacks/actions?workflow=CI\n\n.. image:: https://img.shields.io/pypi/v/django-capture-on-commit-callbacks.svg?style=for-the-badge\n   :target: https://pypi.org/project/django-capture-on-commit-callbacks/\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg?style=for-the-badge\n   :target: https://github.com/psf/black\n\n.. image:: https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white&style=for-the-badge\n   :target: https://github.com/pre-commit/pre-commit\n   :alt: pre-commit\n\nCapture and make assertions on ``transaction.on_commit()`` `callbacks <https://docs.djangoproject.com/en/3.0/topics/db/transactions/#performing-actions-after-commit>`__.\nThis allows you to write your tests with the ``TestCase``, rather than needing the slower ``TransactionTestCase`` to actually commit the transactions.\n\nThis package was made as a first pass for `Django PR #12944 <https://github.com/django/django/pull/12944>`__, which is a solution for `Ticket #30457 \u201con_commit should be triggered in a TestCase\u201d <https://code.djangoproject.com/ticket/30457>`__.\nThe PR has been merged to Django and has been released in version 3.2, so this package can now be considered a backport.\n\nRead more in my blog post `The Fast Way to Test Django transaction.on_commit() Callbacks <https://adamj.eu/tech/2020/05/20/the-fast-way-to-test-django-transaction-on-commit-callbacks/>`__.\n\nInstallation\n============\n\nUse **pip**:\n\n.. code-block:: bash\n\n    python -m pip install django-capture-on-commit-callbacks\n\nRequirements\n============\n\nPython 3.7 to 3.10 supported.\n\nDjango 3.2 to 4.0 supported.\n\n**Note:** This package is not needed on Django 4.0+ and it will error on usage for such versions.\n\n----\n\n**Are your tests slow?**\nCheck out my book `Speed Up Your Django Tests <https://adamchainz.gumroad.com/l/suydt>`__ which covers loads of ways to write faster, more accurate tests.\n\n----\n\nAPI\n===\n\n``capture_on_commit_callbacks(*, using=\"default\", execute=False)``\n------------------------------------------------------------------\n\nActs as a context manager that captures ``on_commit`` callbacks for the given database connection.\nIt returns a list that contains, on exit of the context, the captured callback functions.\nFrom this list you can make assertions on the callbacks or call them to invoke their side effects, emulating a commit.\n\nAll arguments must be passed as keyword arguments.\n\n``using`` is the alias of the database connection to capture callbacks for.\n\n``execute`` specifies whether to call all the callbacks automatically as the context manager exits, if no exception has been raised.\n\nFor example, you can test a commit hook that sends an email like so:\n\n.. code-block:: python\n\n    from django.core import mail\n    from django.test import TestCase\n    from django_capture_on_commit_callbacks import capture_on_commit_callbacks\n\n\n    class ContactTests(TestCase):\n        def test_post(self):\n            with capture_on_commit_callbacks() as callbacks:\n                response = self.client.post(\n                    \"/contact/\",\n                    {\"message\": \"I like your site\"},\n                )\n\n            self.assertEqual(response.status_code, 200)\n\n            self.assertEqual(len(callbacks), 1)\n            # Execute the callback\n            callbacks[0]()\n\n            self.assertEqual(len(mail.outbox), 1)\n            self.assertEqual(mail.outbox[0].subject, \"Contact Form\")\n            self.assertEqual(mail.outbox[0].body, \"I like your site\")\n\nThe same test can be written a bit more succinctly with ``execute=True``:\n\n.. code-block:: python\n\n    from django.core import mail\n    from django.test import TestCase\n    from django_capture_on_commit_callbacks import capture_on_commit_callbacks\n\n\n    class ContactTests(TestCase):\n        def test_post(self):\n            with capture_on_commit_callbacks(execute=True) as callbacks:\n                response = self.client.post(\n                    \"/contact/\",\n                    {\"message\": \"I like your site\"},\n                )\n\n            self.assertEqual(response.status_code, 200)\n\n            self.assertEqual(len(callbacks), 1)\n\n            self.assertEqual(len(mail.outbox), 1)\n            self.assertEqual(mail.outbox[0].subject, \"Contact Form\")\n            self.assertEqual(mail.outbox[0].body, \"I like your site\")\n\n``TestCaseMixin``\n-----------------\n\nA mixin class to be added to your custom ``TestCase`` subclass.\nIt adds one method, ``captureOnCommitCallbacks()`` that aliases ``capture_on_commit_callbacks()``, to match the ``camelCase`` style of unittest assertions.\n\nYou can add to your custom ``TestCase`` classes like so:\n\n.. code-block:: python\n\n    from django import test\n    from django_capture_on_commit_callbacks import TestCaseMixin\n\n\n    class TestCase(TestCaseMixin, test.TestCase):\n        pass\n\nYou could then rewrite the above tests with your custom ``TestCase`` class like so:\n\n.. code-block:: python\n\n    from django.core import mail\n    from example.test import TestCase\n\n\n    class ContactTests(TestCase):\n        def test_post(self):\n            with self.captureOnCommitCallbacks(execute=True) as callbacks:\n                response = self.client.post(\n                    \"/contact/\",\n                    {\"message\": \"I like your site\"},\n                )\n\n            self.assertEqual(response.status_code, 200)\n\n            self.assertEqual(len(callbacks), 1)\n\n            self.assertEqual(len(mail.outbox), 1)\n            self.assertEqual(mail.outbox[0].subject, \"Contact Form\")\n            self.assertEqual(mail.outbox[0].body, \"I like your site\")\n\n\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Capture and make assertions on transaction.on_commit() callbacks.",
    "version": "1.11.0",
    "project_urls": {
        "Changelog": "https://github.com/adamchainz/django-capture-on-commit-callbacks/blob/main/HISTORY.rst",
        "Homepage": "https://github.com/adamchainz/django-capture-on-commit-callbacks",
        "Twitter": "https://twitter.com/adamchainz"
    },
    "split_keywords": [
        "django"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "f08b2f7e3971b7138e6efea1e4792eb8fd2a2391106e8dcaa2bf57561daa51eb",
                "md5": "a633d5f72e382f486174cda6043b5436",
                "sha256": "a75300586390411a7e4641128c4251fdc5db25b6e76543329d82fb2c2bc71163"
            },
            "downloads": -1,
            "filename": "django_capture_on_commit_callbacks-1.11.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "a633d5f72e382f486174cda6043b5436",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7",
            "size": 5301,
            "upload_time": "2022-05-10T12:22:51",
            "upload_time_iso_8601": "2022-05-10T12:22:51.753387Z",
            "url": "https://files.pythonhosted.org/packages/f0/8b/2f7e3971b7138e6efea1e4792eb8fd2a2391106e8dcaa2bf57561daa51eb/django_capture_on_commit_callbacks-1.11.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "64b4b6cd102b08e82b8020896619cbf0df2ade14b17edb7e4a0c5188f2da0a60",
                "md5": "d688bc5f4265a1cb1801d785a4fb5029",
                "sha256": "ee5a79dc74937a0318c192b54d904ce0826ced47748d160bf15324fc77e98c41"
            },
            "downloads": -1,
            "filename": "django-capture-on-commit-callbacks-1.11.0.tar.gz",
            "has_sig": false,
            "md5_digest": "d688bc5f4265a1cb1801d785a4fb5029",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7",
            "size": 6651,
            "upload_time": "2022-05-10T12:22:53",
            "upload_time_iso_8601": "2022-05-10T12:22:53.885866Z",
            "url": "https://files.pythonhosted.org/packages/64/b4/b6cd102b08e82b8020896619cbf0df2ade14b17edb7e4a0c5188f2da0a60/django-capture-on-commit-callbacks-1.11.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2022-05-10 12:22:53",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "adamchainz",
    "github_project": "django-capture-on-commit-callbacks",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "tox": true,
    "lcname": "django-capture-on-commit-callbacks"
}
        
Elapsed time: 0.93389s