django-assert-model-queries


Namedjango-assert-model-queries JSON
Version 1.1.0 PyPI version JSON
download
home_pageNone
SummaryA Django test utility to assert the number of queries per model.
upload_time2024-11-29 21:58:12
maintainerNone
docs_urlNone
authorNone
requires_python>=3.9
licenseNone
keywords django pytest test
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Django Assert Model Queries

This project seeks to assist asserting the number of queries per model
during testing.

**Note:** This does so by monkey-patching the ``SQLCompiler`` classes. It's
not something that should be relied upon in production.

## Installation

  ```shell
  pip install django-assert-model-queries
  ```

## Usage

There are integrations for both pytest and Django / `unittest`. Both of
which use the context manager,
``django_assert_model_queries.AssertModelQueries`` under the
hood.

The basic usage is to define a dictionary of expected queries to be
evaluated at the end of the context manager's scope. If the counts
differ, a helpful error message will be rendered indicating what the
differences were and what *all* the queries were during the context.

```python
from django_assert_model_queries import AssertModelQueries
from testapp.models import Community

with AssertModelQueries({"testapp.Community": 2}):
    Community.objects.create(name="test")
    Community.objects.update(name="test")
```

When an unexpected query runs, this ``AssertModelQueries`` will
tell you which model generated an unexpected query.


### Example error

Here is an example of what you can expect from the tool:

```pycon
>>>  from django_assert_model_queries import AssertModelQueries
>>>  from django.contrib.auth.models import User
>>>  with AssertModelQueries({}):
>>>      User.objects.first()

---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
Cell In[1], line 3
      1 from django_assert_model_queries import AssertModelQueries
      2 from django.contrib.auth.models import User
----> 3 with AssertModelQueries({}):
      4     User.objects.only("id").first()

File ~/site-packages/django_assert_model_queries/test.py:145, in AssertModelQueries.__exit__(self, exc_type, exc_value, traceback)
    142 if exc_type is not None:
    143     return
--> 145 self.handle_assertion(actual, expected)
    146 self.expected_model_counts = None

File ~/site-packages/django_assert_model_queries/test.py:172, in AssertModelQueries.handle_assertion(self, actual, expected)
    170         pytest.fail(self.failure_message(actual, expected))
    171 else:
--> 172     assert actual == expected, self.failure_message(actual, expected)

AssertionError: {'auth.User': 1} != {}
- {'auth.User': 1}
+ {}

All queries:
SELECT "auth_user"."id" FROM "auth_user" ORDER BY "auth_user"."id" ASC LIMIT 1
```

### Integrating with pytest

If you use pytest, you can use the fixture ``assert_model_queries`` as a short-cut.

```python
# pytest example

import pytest
from testapp.models import Community


class TestPytestIntegration:
    @pytest.mark.django_db
    def test_assert_model_queries(self, assert_model_queries):
        with assert_model_queries({"testapp.Community": 1}):
            Community.objects.create(name="test")

        with assert_model_queries({
          "testapp.Community": 2,
          "testapp.Chapter": 1,
          "testapp.Community_topics": 1,
        }):
            Community.objects.all().delete()
```

### Integrating with unittest

If you test with Django's ``TestCase``, inherit from the mixin
``ModelNumQueriesHelper`` to be able to utilize the
``self.assertModelQueries`` assertion method.

```python
# Django TestCase example

from django.test import TestCase
from django_assert_model_queries import AssertModelQueries, ModelNumQueriesHelper
from testapp.models import Community

class TestDjangoIntegration(ModelNumQueriesHelper, TestCase):
    def test_assert_model_num_queries_context(self):
        with AssertModelQueries({"testapp.Community": 1}):
            Community.objects.create(name="test")
        with AssertModelQueries({"testapp.Community": 2, "testapp.Chapter": 1, "testapp.Community_topics": 1}):
            Community.objects.all().delete()

class TestDjangoHelperIntegration(ModelNumQueriesHelper, TestCase):
    def test_helper(self):
        with self.assertModelQueries({"testapp.Community": 1}):
            Community.objects.create(name="test")
        with self.assertModelQueries({"testapp.Community": 2, "testapp.Chapter": 1, "testapp.Community_topics": 1}):
            Community.objects.all().delete()
```

### Complex usages

There are a few parameters that may help in certain scenarios.

- ``ignore``: A collection of models that should be ignored. For example,
  maybe you want to ignore ``Session`` queries if you're using a database
  backed session.
- ``strict=False``: You can limit the count evaluation to just the models
  specified in the ``expect_model_counts`` collection. Be warned, this can
  hide N+1 issues.

To use these, you must specify them when instantiating
``AssertModelQueries``.

```python
from django_assert_model_queries import AssertModelQueries
from django.contrib.sessions.models import Session

assert_context = AssertModelQueries(ignore={Session})
with assert_context({"testapp.Community": 1}):
    do_something()


assert_context = AssertModelQueries(strict=False)
with assert_context({"testapp.Community": 1}):
    do_something()
```

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "django-assert-model-queries",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.9",
    "maintainer_email": null,
    "keywords": "django, pytest, test",
    "author": null,
    "author_email": "Tim Schilling <tim@aspiredu.com>",
    "download_url": "https://files.pythonhosted.org/packages/ad/97/d493a1899a5b6087f4e8c97cbc90dcb379fa6c85ea0768da5bbf9862538e/django_assert_model_queries-1.1.0.tar.gz",
    "platform": null,
    "description": "# Django Assert Model Queries\n\nThis project seeks to assist asserting the number of queries per model\nduring testing.\n\n**Note:** This does so by monkey-patching the ``SQLCompiler`` classes. It's\nnot something that should be relied upon in production.\n\n## Installation\n\n  ```shell\n  pip install django-assert-model-queries\n  ```\n\n## Usage\n\nThere are integrations for both pytest and Django / `unittest`. Both of\nwhich use the context manager,\n``django_assert_model_queries.AssertModelQueries`` under the\nhood.\n\nThe basic usage is to define a dictionary of expected queries to be\nevaluated at the end of the context manager's scope. If the counts\ndiffer, a helpful error message will be rendered indicating what the\ndifferences were and what *all* the queries were during the context.\n\n```python\nfrom django_assert_model_queries import AssertModelQueries\nfrom testapp.models import Community\n\nwith AssertModelQueries({\"testapp.Community\": 2}):\n    Community.objects.create(name=\"test\")\n    Community.objects.update(name=\"test\")\n```\n\nWhen an unexpected query runs, this ``AssertModelQueries`` will\ntell you which model generated an unexpected query.\n\n\n### Example error\n\nHere is an example of what you can expect from the tool:\n\n```pycon\n>>>  from django_assert_model_queries import AssertModelQueries\n>>>  from django.contrib.auth.models import User\n>>>  with AssertModelQueries({}):\n>>>      User.objects.first()\n\n---------------------------------------------------------------------------\nAssertionError                            Traceback (most recent call last)\nCell In[1], line 3\n      1 from django_assert_model_queries import AssertModelQueries\n      2 from django.contrib.auth.models import User\n----> 3 with AssertModelQueries({}):\n      4     User.objects.only(\"id\").first()\n\nFile ~/site-packages/django_assert_model_queries/test.py:145, in AssertModelQueries.__exit__(self, exc_type, exc_value, traceback)\n    142 if exc_type is not None:\n    143     return\n--> 145 self.handle_assertion(actual, expected)\n    146 self.expected_model_counts = None\n\nFile ~/site-packages/django_assert_model_queries/test.py:172, in AssertModelQueries.handle_assertion(self, actual, expected)\n    170         pytest.fail(self.failure_message(actual, expected))\n    171 else:\n--> 172     assert actual == expected, self.failure_message(actual, expected)\n\nAssertionError: {'auth.User': 1} != {}\n- {'auth.User': 1}\n+ {}\n\nAll queries:\nSELECT \"auth_user\".\"id\" FROM \"auth_user\" ORDER BY \"auth_user\".\"id\" ASC LIMIT 1\n```\n\n### Integrating with pytest\n\nIf you use pytest, you can use the fixture ``assert_model_queries`` as a short-cut.\n\n```python\n# pytest example\n\nimport pytest\nfrom testapp.models import Community\n\n\nclass TestPytestIntegration:\n    @pytest.mark.django_db\n    def test_assert_model_queries(self, assert_model_queries):\n        with assert_model_queries({\"testapp.Community\": 1}):\n            Community.objects.create(name=\"test\")\n\n        with assert_model_queries({\n          \"testapp.Community\": 2,\n          \"testapp.Chapter\": 1,\n          \"testapp.Community_topics\": 1,\n        }):\n            Community.objects.all().delete()\n```\n\n### Integrating with unittest\n\nIf you test with Django's ``TestCase``, inherit from the mixin\n``ModelNumQueriesHelper`` to be able to utilize the\n``self.assertModelQueries`` assertion method.\n\n```python\n# Django TestCase example\n\nfrom django.test import TestCase\nfrom django_assert_model_queries import AssertModelQueries, ModelNumQueriesHelper\nfrom testapp.models import Community\n\nclass TestDjangoIntegration(ModelNumQueriesHelper, TestCase):\n    def test_assert_model_num_queries_context(self):\n        with AssertModelQueries({\"testapp.Community\": 1}):\n            Community.objects.create(name=\"test\")\n        with AssertModelQueries({\"testapp.Community\": 2, \"testapp.Chapter\": 1, \"testapp.Community_topics\": 1}):\n            Community.objects.all().delete()\n\nclass TestDjangoHelperIntegration(ModelNumQueriesHelper, TestCase):\n    def test_helper(self):\n        with self.assertModelQueries({\"testapp.Community\": 1}):\n            Community.objects.create(name=\"test\")\n        with self.assertModelQueries({\"testapp.Community\": 2, \"testapp.Chapter\": 1, \"testapp.Community_topics\": 1}):\n            Community.objects.all().delete()\n```\n\n### Complex usages\n\nThere are a few parameters that may help in certain scenarios.\n\n- ``ignore``: A collection of models that should be ignored. For example,\n  maybe you want to ignore ``Session`` queries if you're using a database\n  backed session.\n- ``strict=False``: You can limit the count evaluation to just the models\n  specified in the ``expect_model_counts`` collection. Be warned, this can\n  hide N+1 issues.\n\nTo use these, you must specify them when instantiating\n``AssertModelQueries``.\n\n```python\nfrom django_assert_model_queries import AssertModelQueries\nfrom django.contrib.sessions.models import Session\n\nassert_context = AssertModelQueries(ignore={Session})\nwith assert_context({\"testapp.Community\": 1}):\n    do_something()\n\n\nassert_context = AssertModelQueries(strict=False)\nwith assert_context({\"testapp.Community\": 1}):\n    do_something()\n```\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "A Django test utility to assert the number of queries per model.",
    "version": "1.1.0",
    "project_urls": {
        "Changelog": "https://github.com/aspiredu/django-assert-model-queries/blob/main/CHANGELOG.md",
        "Homepage": "https://github.com/aspiredu/django-assert-model-queries",
        "Issues": "https://github.com/aspiredu/django-assert-model-queries/issues"
    },
    "split_keywords": [
        "django",
        " pytest",
        " test"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "626b7b24b27182aff46a36e3469388fee09fd664b909358e2736e86b82160638",
                "md5": "1b0d798b4eca66d9bc88e8e70347aa2a",
                "sha256": "e09cd62780b0e808fa933200fb7cc699b9d5061cd16dba6ce666559243b7581b"
            },
            "downloads": -1,
            "filename": "django_assert_model_queries-1.1.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "1b0d798b4eca66d9bc88e8e70347aa2a",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9",
            "size": 7975,
            "upload_time": "2024-11-29T21:57:56",
            "upload_time_iso_8601": "2024-11-29T21:57:56.724281Z",
            "url": "https://files.pythonhosted.org/packages/62/6b/7b24b27182aff46a36e3469388fee09fd664b909358e2736e86b82160638/django_assert_model_queries-1.1.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "ad97d493a1899a5b6087f4e8c97cbc90dcb379fa6c85ea0768da5bbf9862538e",
                "md5": "b473c37598afa4b3f693ebb2a32cab15",
                "sha256": "e9d77f03fcc6adc12175bd2b9b59bd43f2990547f4e68e53b3a647a1b5e9d935"
            },
            "downloads": -1,
            "filename": "django_assert_model_queries-1.1.0.tar.gz",
            "has_sig": false,
            "md5_digest": "b473c37598afa4b3f693ebb2a32cab15",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9",
            "size": 21930,
            "upload_time": "2024-11-29T21:58:12",
            "upload_time_iso_8601": "2024-11-29T21:58:12.009454Z",
            "url": "https://files.pythonhosted.org/packages/ad/97/d493a1899a5b6087f4e8c97cbc90dcb379fa6c85ea0768da5bbf9862538e/django_assert_model_queries-1.1.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-11-29 21:58:12",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "aspiredu",
    "github_project": "django-assert-model-queries",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "tox": true,
    "lcname": "django-assert-model-queries"
}
        
Elapsed time: 1.10039s