pytest-django allows you to test your Django project/applications with the pytest testing tool.

Overview
PyPI Version Supported Python versions Build Status Coverage

Welcome to pytest-django!

pytest-django allows you to test your Django project/applications with the pytest testing tool.

Install pytest-django

pip install pytest-django

Why would I use this instead of Django's manage.py test command?

Running your test suite with pytest-django allows you to tap into the features that are already present in pytest. Here are some advantages:

  • Manage test dependencies with pytest fixtures.
  • Less boilerplate tests: no need to import unittest, create a subclass with methods. Write tests as regular functions.
  • Database re-use: no need to re-create the test database for every test run.
  • Run tests in multiple processes for increased speed (with the pytest-xdist plugin).
  • Make use of other pytest plugins.
  • Works with both worlds: Existing unittest-style TestCase's still work without any modifications.

See the pytest documentation for more information on pytest itself.

Comments
  • Create --querycount parameter

    Create --querycount parameter

    It displays a list of top N tests with most queries.

    I was inspired by the --duration parameter of pytest and tried to make work as similar as a could.

    Note that I used the report sections to store the executed queries. Even though I'm not sure it is the best way to do that, it had a nice side effect: The executed queries are displayed when a test fails.

    TODO:

    • [ ] capture all connections; if there are multiple this should be reported separately (but for the single nodeid, similar to setup/call/teardown (see 4. below))
    • [ ] revisit tests to check if it is using the test DB always really
    • [x] counts appear to be wrong: I get the same with "teardown" as with "call" always (fixed in diff/patch)
    • [ ] combine counts per nodeid, but only list counts for setup, call, and teardown in parentheses with it.
    • [ ] currently you will get the captured queries in case of failures (and -s I assume?). There could also be a django_db_log_queries mark and fixture (context manager) that would do the same, but then could be used on a single test for debugging. This should get refactored to provide this easily.
    • [ ] rebase on master for and refactor with _assert_num_queries

    IDEAS:

    • [ ] default to 10 for --querycount, i.e. do not require an argument?
    enhancement 
    opened by renanivo 58
  • Plugin stops testing non-django projects

    Plugin stops testing non-django projects

    Hi

    When the plugin is installed testing a non-django project without having DJANGO_SETTINGS_MODULE results in an error. The reason (AFAIK) is that pytest_django.plugin, which is registered as the pytest11 entrypoint via "from .plugin import *" in pytest_django.init, does a direct "from django.conf import settings".

    I'm not immediately sure how the plugin can detect it is testing a django application in order to decide to activate itself or not. But I think it would be beneficial to not have pytest-django break normal test runs by default.

    Regards, Floris

    opened by flub 36
  • Add initial approach to put Django's asserts into pytest's namespace. Issue #97 (was: Pull Request #144)

    Add initial approach to put Django's asserts into pytest's namespace. Issue #97 (was: Pull Request #144)

    I've only addressed the straight-forward things from the code review feedback in PR #144 for now.

    Original issue: https://github.com/pytest-dev/pytest-django/issues/97

    enhancement 
    opened by bittner 33
  • Adds tests for invalid template variables

    Adds tests for invalid template variables

    Django catches all VariableDoesNotExist exceptions to replace them in templates with a modifiable string that you can define in your settings. Sadly that doesn't allow you to find them in unit tests.

    _fail_for_invalid_template_variable sets the setting TEMPLATE_STRING_IF_INVALID to a custom class that not only fails the current test but prints a pretty message including the template name.

    A new marker allows disabling this behavior, eg:

    @pytest.mark.ignore_template_errors
    def test_something():
        pass
    

    This marker sets the setting to None, if you want it to be a string, you can use the settings fixture to set it to your desired value.

    enhancement 
    opened by codingjoe 31
  • conftest.py presence changes sys.path and settings import

    conftest.py presence changes sys.path and settings import

    running py.test with DJANGO_SETTINGS_MODULE=myproject.settings py.test fails if there is no conftest.py file in root folder with ERROR: Could not import settings 'myproject.settings' (Is it on sys.path?): No module named myproject.settings

    opened by krya 26
  • pytest 5.4 skips Django's teardown (causing e.g.

    pytest 5.4 skips Django's teardown (causing e.g. "connection already closed" errors)

    pytest-django==3.5.1 django versions tested: 2.2.11 and 3.0.4

    When one test fails, all tests which use database launched after this test will fail with traceback:

    test/apiv2/put_inputevent__test.py:34: 
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    /home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/model_mommy/mommy.py:54: in make
        return mommy.make(_save_kwargs=_save_kwargs, **attrs)
    /home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/model_mommy/mommy.py:228: in make
        return self._make(commit=True, commit_related=True, _save_kwargs=_save_kwargs, **attrs)
    /home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/model_mommy/mommy.py:265: in _make
        instance = self.instance(self.model_attrs, _commit=commit, _save_kwargs=_save_kwargs)
    /home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/model_mommy/mommy.py:289: in instance
        instance.save(**_save_kwargs)
    /home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/django/db/models/base.py:741: in save
        force_update=force_update, update_fields=update_fields)
    /home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/django/db/models/base.py:779: in save_base
        force_update, using, update_fields,
    /home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/django/db/models/base.py:851: in _save_table
        forced_update)
    /home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/django/db/models/base.py:900: in _do_update
        return filtered._update(values) > 0
    /home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/django/db/models/query.py:760: in _update
        return query.get_compiler(self.db).execute_sql(CURSOR)
    /home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/django/db/models/sql/compiler.py:1469: in execute_sql
        cursor = super().execute_sql(result_type)
    /home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/django/db/models/sql/compiler.py:1138: in execute_sql
        cursor = self.connection.cursor()
    /home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/django/db/backends/base/base.py:256: in cursor
        return self._cursor()
    /home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/django/db/backends/base/base.py:235: in _cursor
        return self._prepare_cursor(self.create_cursor(name))
    /home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/django/db/utils.py:89: in __exit__
        raise dj_exc_value.with_traceback(traceback) from exc_value
    /home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/django/db/backends/base/base.py:235: in _cursor
        return self._prepare_cursor(self.create_cursor(name))
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    self = <django.db.backends.postgresql.base.DatabaseWrapper object at 0x7fe8150ed208>, name = None
    
        def create_cursor(self, name=None):
            if name:
                # In autocommit mode, the cursor will be used outside of a
                # transaction, hence use a holdable cursor.
                cursor = self.connection.cursor(name, scrollable=False, withhold=self.connection.autocommit)
            else:
    >           cursor = self.connection.cursor()
    E           django.db.utils.InterfaceError: connection already closed
    
    /home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/django/db/backends/postgresql/base.py:223: InterfaceError
    
    

    Downgrading to pytest==5.3.5 fixes the issue.

    Not yet sure if this is pytest issue or pytest-django.

    bug 
    opened by Fak3 25
  • Fixed #136 - fix the settings fixture for certain settings.

    Fixed #136 - fix the settings fixture for certain settings.

    When changing/deleting a setting, the django.test.signals.setting_changed fixture will be sent, just like Django's override_settings decorator.

    Refs #93, #46.

    more and more apps are using this signal to clean their caches, so more and more settings can't be changed with this fixture

    opened by syphar 25
  • Tests using live_server fixture removing data from data migrations

    Tests using live_server fixture removing data from data migrations

    I've created a simple test case to reproduce this behavior https://github.com/ekiro/case_pytest/blob/master/app/tests.py which fails after second test using live_server fixture. MyModel objects are created in migration, using RunPython. It seems like after any test with live_server, every row from the database is truncated. Both, postgresql and sqlite3 was tested.

    EDIT: Tests

    """
    MyModel objects are created in migration
    Test results:
        app/tests.py::test_no_live_server PASSED
        app/tests.py::test_live_server PASSED
        app/tests.py::test_live_server2 FAILED
        app/tests.py::test_no_live_server_after_live_server FAILED
    """
    
    import pytest
    
    from .models import MyModel
    
    
    @pytest.mark.django_db()
    def test_no_live_server():
        """Passed"""
        assert MyModel.objects.count() == 10
    
    
    @pytest.mark.django_db()
    def test_live_server(live_server):
        """Passed"""
        assert MyModel.objects.count() == 10
    
    
    @pytest.mark.django_db()
    def test_live_server2(live_server):
        """Failed, because count() returns 0"""
        assert MyModel.objects.count() == 10
    
    
    @pytest.mark.django_db()
    def test_no_live_server_after_live_server():
        """Failed, because count() returns 0"""
        assert MyModel.objects.count() == 10
    
    opened by ekiro 23
  • New release?

    New release?

    Do the maintainers have plans to cut the next release? A few projects at my job depend on some of the new features such as django_assert_num_queries.

    If there are any blockers to release, I'd be glad to help out.

    opened by sloria 22
  • Should automatically call django.setup() on django 1.7

    Should automatically call django.setup() on django 1.7

    For now I have this in my conftest.py:

    try:
        from django import setup
    except ImportError:
        pass
    else:
        def pytest_configure():
            setup()
    

    Without it I have these mind-boggling errors (on django 1.7b4):

    Traceback (most recent call last):
      File "/home/ionel/osp/django-admin-utils/.tox/3.4-1.7/lib/python3.4/site-packages/django/core/handlers/base.py", line 111, in get_response
        response = wrapped_callback(request, *callback_args, **callback_kwargs)
      File "/home/ionel/osp/django-admin-utils/.tox/3.4-1.7/lib/python3.4/site-packages/django/contrib/admin/sites.py", line 225, in wrapper
        return self.admin_view(view, cacheable)(*args, **kwargs)
      File "/home/ionel/osp/django-admin-utils/.tox/3.4-1.7/lib/python3.4/site-packages/django/utils/decorators.py", line 105, in _wrapped_view
        response = view_func(request, *args, **kwargs)
      File "/home/ionel/osp/django-admin-utils/.tox/3.4-1.7/lib/python3.4/site-packages/django/views/decorators/cache.py", line 52, in _wrapped_view_func
        response = view_func(request, *args, **kwargs)
      File "/home/ionel/osp/django-admin-utils/.tox/3.4-1.7/lib/python3.4/site-packages/django/contrib/admin/sites.py", line 204, in inner
        return view(request, *args, **kwargs)
      File "/home/ionel/osp/django-admin-utils/.tox/3.4-1.7/lib/python3.4/site-packages/django/views/decorators/cache.py", line 52, in _wrapped_view_func
        response = view_func(request, *args, **kwargs)
      File "/home/ionel/osp/django-admin-utils/.tox/3.4-1.7/lib/python3.4/site-packages/django/contrib/admin/sites.py", line 401, in index
        'app_url': reverse('admin:app_list', kwargs={'app_label': app_label}, current_app=self.name),
      File "/home/ionel/osp/django-admin-utils/.tox/3.4-1.7/lib/python3.4/site-packages/django/core/urlresolvers.py", line 542, in reverse
        return iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs))
      File "/home/ionel/osp/django-admin-utils/.tox/3.4-1.7/lib/python3.4/site-packages/django/core/urlresolvers.py", line 459, in _reverse_with_prefix
        (lookup_view_s, args, kwargs, len(patterns), patterns))
    django.core.urlresolvers.NoReverseMatch: Reverse for 'app_list' with arguments '()' and keyword arguments '{'app_label': 'auth'}' not found. 1 pattern(s) tried: ['admin/(?P<app_label>test_app)/$']
    
    bug 
    opened by ionelmc 22
  • INTERNALERROR> Failed: Database access not allowed

    INTERNALERROR> Failed: Database access not allowed

    I have been facing this issue:

    INTERNALERROR> Traceback (most recent call last):
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/_pytest/main.py", line 203, in wrap_session
    INTERNALERROR>     session.exitstatus = doit(config, session) or 0
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/_pytest/main.py", line 243, in _main
    INTERNALERROR>     config.hook.pytest_runtestloop(session=session)
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/pluggy/hooks.py", line 289, in __call__
    INTERNALERROR>     return self._hookexec(self, self.get_hookimpls(), kwargs)
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/pluggy/manager.py", line 68, in _hookexec
    INTERNALERROR>     return self._inner_hookexec(hook, methods, kwargs)
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/pluggy/manager.py", line 62, in <lambda>
    INTERNALERROR>     firstresult=hook.spec.opts.get("firstresult") if hook.spec else False,
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/pluggy/callers.py", line 208, in _multicall
    INTERNALERROR>     return outcome.get_result()
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/pluggy/callers.py", line 80, in get_result
    INTERNALERROR>     raise ex[1].with_traceback(ex[2])
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/pluggy/callers.py", line 187, in _multicall
    INTERNALERROR>     res = hook_impl.function(*args)
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/_pytest/main.py", line 264, in pytest_runtestloop
    INTERNALERROR>     item.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem)
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/pluggy/hooks.py", line 289, in __call__
    INTERNALERROR>     return self._hookexec(self, self.get_hookimpls(), kwargs)
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/pluggy/manager.py", line 68, in _hookexec
    INTERNALERROR>     return self._inner_hookexec(hook, methods, kwargs)
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/pluggy/manager.py", line 62, in <lambda>
    INTERNALERROR>     firstresult=hook.spec.opts.get("firstresult") if hook.spec else False,
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/pluggy/callers.py", line 208, in _multicall
    INTERNALERROR>     return outcome.get_result()
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/pluggy/callers.py", line 80, in get_result
    INTERNALERROR>     raise ex[1].with_traceback(ex[2])
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/pluggy/callers.py", line 187, in _multicall
    INTERNALERROR>     res = hook_impl.function(*args)
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/_pytest/runner.py", line 78, in pytest_runtest_protocol
    INTERNALERROR>     runtestprotocol(item, nextitem=nextitem)
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/_pytest/runner.py", line 87, in runtestprotocol
    INTERNALERROR>     rep = call_and_report(item, "setup", log)
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/_pytest/runner.py", line 175, in call_and_report
    INTERNALERROR>     report = hook.pytest_runtest_makereport(item=item, call=call)
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/pluggy/hooks.py", line 289, in __call__
    INTERNALERROR>     return self._hookexec(self, self.get_hookimpls(), kwargs)
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/pluggy/manager.py", line 68, in _hookexec
    INTERNALERROR>     return self._inner_hookexec(hook, methods, kwargs)
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/pluggy/manager.py", line 62, in <lambda>
    INTERNALERROR>     firstresult=hook.spec.opts.get("firstresult") if hook.spec else False,
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/pluggy/callers.py", line 203, in _multicall
    INTERNALERROR>     gen.send(outcome)
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/_pytest/skipping.py", line 127, in pytest_runtest_makereport
    INTERNALERROR>     rep = outcome.get_result()
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/pluggy/callers.py", line 80, in get_result
    INTERNALERROR>     raise ex[1].with_traceback(ex[2])
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/pluggy/callers.py", line 187, in _multicall
    INTERNALERROR>     res = hook_impl.function(*args)
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/_pytest/runner.py", line 271, in pytest_runtest_makereport
    INTERNALERROR>     excinfo, style=item.config.option.tbstyle
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/_pytest/nodes.py", line 284, in _repr_failure_py
    INTERNALERROR>     truncate_locals=truncate_locals,
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/_pytest/_code/code.py", line 556, in getrepr
    INTERNALERROR>     return fmt.repr_excinfo(self)
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/_pytest/_code/code.py", line 806, in repr_excinfo
    INTERNALERROR>     reprtraceback = self.repr_traceback(excinfo)
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/_pytest/_code/code.py", line 751, in repr_traceback
    INTERNALERROR>     reprentry = self.repr_traceback_entry(entry, einfo)
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/_pytest/_code/code.py", line 710, in repr_traceback_entry
    INTERNALERROR>     reprargs = self.repr_args(entry) if not short else None
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/_pytest/_code/code.py", line 628, in repr_args
    INTERNALERROR>     args.append((argname, self._saferepr(argvalue)))
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/_pytest/_code/code.py", line 622, in _saferepr
    INTERNALERROR>     return saferepr(obj)
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/_pytest/_io/saferepr.py", line 72, in saferepr
    INTERNALERROR>     return srepr.repr(obj)
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/_pytest/_io/saferepr.py", line 12, in repr
    INTERNALERROR>     return self._callhelper(reprlib.Repr.repr, self, x)
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/_pytest/_io/saferepr.py", line 38, in _callhelper
    INTERNALERROR>     s = call(x, *args)
    INTERNALERROR>   File "/usr/local/lib/python3.6/reprlib.py", line 55, in repr
    INTERNALERROR>     return self.repr1(x, self.maxlevel)
    INTERNALERROR>   File "/usr/local/lib/python3.6/reprlib.py", line 65, in repr1
    INTERNALERROR>     return self.repr_instance(x, level)
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/_pytest/_io/saferepr.py", line 33, in repr_instance
    INTERNALERROR>     return self._callhelper(repr, x)
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/_pytest/_io/saferepr.py", line 38, in _callhelper
    INTERNALERROR>     s = call(x, *args)
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py", line 244, in __repr__
    INTERNALERROR>     data = list(self[:REPR_OUTPUT_SIZE + 1])
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py", line 268, in __iter__
    INTERNALERROR>     self._fetch_all()
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py", line 1186, in _fetch_all
    INTERNALERROR>     self._result_cache = list(self._iterable_class(self))
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py", line 54, in __iter__
    INTERNALERROR>     results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1063, in execute_sql
    INTERNALERROR>     cursor = self.connection.cursor()
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/django/db/backends/base/base.py", line 255, in cursor
    INTERNALERROR>     return self._cursor()
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/django/db/backends/base/base.py", line 232, in _cursor
    INTERNALERROR>     self.ensure_connection()
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/pytest_django/plugin.py", line 749, in _blocking_wrapper
    INTERNALERROR>     "Database access not allowed, "
    INTERNALERROR>   File "/usr/local/lib/python3.6/site-packages/_pytest/outcomes.py", line 113, in fail
    INTERNALERROR>     raise Failed(msg=msg, pytrace=pytrace)
    INTERNALERROR> Failed: Database access not allowed, use the "django_db" mark, or the "db" or "transactional_db" fixtures to enable it.
    

    It happens when I have a FK in a model with a default value set via a function that looks like this:

    def default_value():
        return ModelA.objects.get(name='foo').pk
    

    It happened when I used the django_db mark, even if it was on an empty test and even if this was the only test:

    @pytest.mark.django_db
    def test_this():
        pass
    

    If I comment the decorator, it wouldn't happen.

    I feel the error has to do with the migrations.

    Thank you!

    PS: Edited to remove information that became irrelevant (see my comment below)

    bug 
    opened by cmermingas 21
  • Add `pattern` argument to django_assert_num_queries fixture

    Add `pattern` argument to django_assert_num_queries fixture

    This optional argument allows to filter the queries to take into account for the assertion.

    It may be useful to check for the count of only certain queries. For example, a use case of mine is to skip SAVEPOINT queries by using:

    NO_SAVEPOINT_PATTERN=r'(?!^(ROLLBACK TO |RELEASE )?SAVEPOINT [`"].+[`"]$)'
    ...
    with django_assert_num_queries(n, pattern=NO_SAVEPOINT_PATTERN):
       ...
    
    opened by qarlosh 0
  • How to test stripe webhook using pytest-django

    How to test stripe webhook using pytest-django

    I have a docker-compose based development environment with

    services:
        django:
        postgres:
        stripe:
            command: listen --forward-to http://django:8000/stripe/webhook
    

    When the user uses stripe to make a payment, an event is forwarded by stripe to a webhook http://django:800/stripe/webhook, handled by the django instance.

    When I use pytest to test the service, the following happens (as far as I understand):

    1. django is still running with access to the regular database
    2. A live_server with --ds=config.settings.test is created with access to the test database
    3. When a payment is made during testing, stripe still forwards the request to django, which accesses the regular database, NOT the test database that is hooked to live_server, and the test payment would fail.

    To fix this problem, we may

    1. Fix stripe: Somehow configure stripe to --forward-to live_server.url/stripe/webhoo. This is what is supposed to happen but requires a different stripe cli instance to be created after live_server.url is determined.
    2. Keep --forward-to to the regular django instance, but django (NOT live_server) will access the test database to complete the test. This may be easier but I am not sure how to configure django to access the test database.

    Does anyone have any suggestions on how to do this properly?

    Edit: A third option maybe running the tests on django directly without firing up a live_server, and using the normal database. The trouble is then how to direct pytest-django to NOT use the test database.

    opened by BoPeng 1
  • Idea: Add support to specify db suffix from command line

    Idea: Add support to specify db suffix from command line

    I am working on a big project which has a lot of migrations and I am bouncing from one branch to another where there will be differences between migrations (eg develop vs master). So sometimes I cannot reuse the existing test database when I checkout a different branch.

    So my thought was to add a specific db suffix that can be used to specify different test db (based on my branch). The following code did the trick:

    from pytest_django.fixtures import _set_suffix_to_test_databases
    from pytest_django.lazy_django import skip_if_no_django
    
     def pytest_addoption(parser) -> None:
        """pytest django plugin enhancements.
        Adds pytest command line argument to specify test database suffix.
        """
        group = parser.getgroup("django")
        group.addoption(
            "--db-suffix",
            action="store",
            dest="db_suffix",
            default=None,
            help="Use specific test database suffix.",
        )
    
    
    @pytest.fixture(scope="session")
    def django_db_suffix(request) -> str:
        return request.config.getvalue("db_suffix")
    
    
    @pytest.fixture(scope="session", autouse=True)
    def django_db_modify_db_settings_config_suffix(django_db_suffix) -> None:
        skip_if_no_django()
    
        if django_db_suffix:
            _set_suffix_to_test_databases(suffix=django_db_suffix)
    

    I was wondering if this can be added to that library and help others.

    opened by gmuj 0
  • Idea: Ability to capture queries but not fail the test

    Idea: Ability to capture queries but not fail the test

    Let's say we've got a following test:

    # models.py
    from django.db import models
    
    
    class Post(models.Model):
        title = models.CharField(max_length=255)
    
    
    class PostHistory(models.Model):
        post = models.ForeignKey(Post, on_delete=models.CASCADE)
    
    
    def create_post(title):
        post = Post.objects.create(title=title)
        PostHistory.objects.create(post=post)
    
    
    # test_models.py
    def test_saving_element_works(django_assert_num_queries):
        with django_assert_num_queries(2):
            create_post("foo")
    
        post = Post.objects.first()
        assert post
        assert post.title == 'foo'
        assert PostHistory.objects.filter(post=post).count() == 1
    

    This test would pass of course just fine.

    Let's say For some reason I remove the line PostHistory.objects.create(post=post).

    Now the test fails with the number of queries being incorrect (1 instead of 2). But in order to debug this using the following test, I'd have to either comment out the num_queries assertion, or have a separate test for just testing the query count, but that's a solution we don't really want, as there'll always be a test case that tests the logic, but doesn't really check if the queries match (you could have n-queries inside if-statement for example).

    As a potential solution for this I was thinking of having a way to not fail the test (only for development), but rather only display the message as a warning.

    I think ideally, we could add a CLI flag in the lines of --no-fail-on-django-query-count or something similar.

    I'm happy to work on this, just wanted to see if there's any interest in adding something like that, or if there's a better solution to this issue.

    opened by MichalPodeszwa 1
  • Move thread activation to start method

    Move thread activation to start method

    This moves activation of LiveServer.thread to a method. My primary motivation here is to delay thread activation so I can change the parameters of the thread in an overriden live_server fixture. This provides a work-around to issue #294 using the following override:

    import os
    
    import pytest
    from django.test.testcases import _StaticFilesHandler
    from pytest_django import live_server_helper
    from pytest_django.lazy_django import skip_if_no_django
    
    
    @pytest.fixture(scope="session")
    def live_server(request):
        skip_if_no_django()
    
        addr = (
            request.config.getvalue("liveserver")
            or os.getenv("DJANGO_LIVE_TEST_SERVER_ADDRESS")
            or "localhost"
        )
    
        server = live_server_helper.LiveServer(addr)
        server.thread.static_handler = _StaticFilesHandler  # Force _StaticFilesHandler
        server.start()
        request.addfinalizer(server.stop)
    
        return server
    
    opened by samamorgan 6
Releases(v4.5.2)
  • v4.5.2(Dec 7, 2021)

  • v4.5.1(Dec 2, 2021)

  • v4.5.0(Dec 1, 2021)

  • v4.3.0(May 19, 2021)

  • v4.1.0(Oct 22, 2020)

  • v4.0.0(Oct 16, 2020)

  • v3.8.0(Feb 6, 2020)

  • v3.5.0(Jun 3, 2019)

    Features ^^^^^^^^

    • Run tests in the same order as Django (#223)

    • Use verbosity=0 with disabled migrations (#729, #730)

    Bugfixes ^^^^^^^^

    • django_db_setup: warn instead of crash with teardown errors (#726)

    Misc ^^^^

    • tests: fix test_sqlite_database_renamed (#739, #741)

    • tests/conftest.py: move import of db_helpers (#737)

    • Cleanup/improve coverage, mainly with tests (#706)

    • Slightly revisit unittest handling (#740)

    Source code(tar.gz)
    Source code(zip)
  • 3.4.4(Nov 13, 2018)

    3.4.4 (2018-11-13)

    Bugfixes ^^^^^^^^

    • Refine the django.conf module check to see if the settings really are configured (#668).
    • Avoid crash after OSError during Django path detection (#664).

    Features ^^^^^^^^

    • Add parameter info to fixture assert_num_queries to display additional message on failure (#663).

    Docs ^^^^

    • Improve doc for django_assert_num_queries/django_assert_max_num_queries.
    • Add warning about sqlite specific snippet + fix typos (#666).

    Misc ^^^^

    • MANIFEST.in: include tests for downstream distros (#653).
    • Ensure that the LICENSE file is included in wheels (#665).
    • Run black on source.
    Source code(tar.gz)
    Source code(zip)
  • 3.4.2(Aug 20, 2018)

    3.4.2 (2018-08-20)

    Bugfixes ^^^^^^^^

    • Changed dependency for pathlib to pathlib2 (#636).
    • Fixed code for inserting the project to sys.path with pathlib to use an absolute path, regression in 3.4.0 (#637, #638).
    Source code(tar.gz)
    Source code(zip)
  • 3.4.0(Aug 16, 2018)

    3.4.0 (2018-08-16)

    Features ^^^^^^^^

    • Added new fixture :fixture:django_assert_max_num_queries (#547).
    • Added support for connection and returning the wrapped context manager with :fixture:django_assert_num_queries (#547).
    • Added support for resetting sequences via :fixture:django_db_reset_sequences (#619).

    Bugfixes ^^^^^^^^

    • Made sure to not call django.setup() multiple times (#629, #531).

    Compatibility ^^^^^^^^^^^^^

    • Removed py dependency, use pathlib instead (#631).
    Source code(tar.gz)
    Source code(zip)
  • 3.3.1(Jun 21, 2018)

    3.3.1 (2018-06-21)

    Bug fixes ^^^^^^^^^

    • Fixed test for classmethod with Django TestCases again (#618, introduced in #598 (3.3.0)).

    Compatibility ^^^^^^^^^^^^^

    • Support Django 2.1 (no changes necessary) (#614).
    Source code(tar.gz)
    Source code(zip)
  • 3.3.0(Jun 15, 2018)

    Features ^^^^^^^^

    • Added new fixtures django_mail_dnsname and django_mail_patch_dns, used by mailoutbox to monkeypatch the DNS_NAME used in :py:mod:django.core.mail to improve performance and reproducibility.

    Bug fixes ^^^^^^^^^

    • Fixed test for classmethod with Django TestCases (#597, #598).
    • Fixed RemovedInPytest4Warning: MarkInfo objects are deprecated (#596, #603)
    • Fixed scope of overridden settings with live_server fixture: previously they were visible to following tests (#612).
    Source code(tar.gz)
    Source code(zip)
  • 3.2.0(Apr 14, 2018)

    3.2.0

    Features ^^^^^^^^

    • Added new fixture django_assert_num_queries for testing the number of database queries (#387).
    • --fail-on-template-vars has been improved and should now return full/absolute path (#470).
    • Support for setting the live server port (#500).
    • unittest: help with setUpClass not being a classmethod (#544).

    Bug fixes ^^^^^^^^^

    • Fix --reuse-db and --create-db not working together (#411).
    • Numerous fixes in the documentation. These should not go unnoticed 🌟

    Compatibility ^^^^^^^^^^^^^

    • Support for Django 2.0 has been added.
    • Support for Django before 1.8 has been dropped.
    Source code(tar.gz)
    Source code(zip)
REST API with Django and SQLite3

REST API with Django and SQLite3

Luis Quiñones Requelme 1 Nov 07, 2021
A pickled object field for Django

django-picklefield About django-picklefield provides an implementation of a pickled object field. Such fields can contain any picklable objects. The i

Gintautas Miliauskas 167 Oct 18, 2022
Django-Audiofield is a simple app that allows Audio files upload, management and conversion to different audio format (mp3, wav & ogg), which also makes it easy to play audio files into your Django application.

Django-Audiofield Description: Django Audio Management Tools Maintainer: Areski Contributors: list of contributors Django-Audiofield is a simple app t

Areski Belaid 167 Nov 10, 2022
Simple XML-RPC and JSON-RPC server for modern Django

django-modern-rpc Build an XML-RPC and/or JSON-RPC server as part of your Django project. Major Django and Python versions are supported Main features

Antoine Lorence 82 Dec 04, 2022
Pinax is an open-source platform built on the Django Web Framework.

Symposion Pinax Pinax is an open-source platform built on the Django Web Framework. It is an ecosystem of reusable Django apps, themes, and starter pr

Pinax Project 295 Mar 20, 2022
Median and percentile for Django and MongoEngine

Tailslide Median and percentile for Django and MongoEngine Supports: PostgreSQL SQLite MariaDB MySQL (with an extension) SQL Server MongoDB 🔥 Uses na

Andrew Kane 4 Jan 15, 2022
Build reusable components in Django without writing a single line of Python.

Build reusable components in Django without writing a single line of Python. {% #quote %} {% quote_photo src="/project-hail-mary.jpg" %} {% #quot

Mitchel Cabuloy 277 Jan 02, 2023
Per object permissions for Django

django-guardian django-guardian is an implementation of per object permissions [1] on top of Django's authorization backend Documentation Online docum

3.3k Jan 04, 2023
Django CacheMiddleware has a multi-threading issue with pylibmc

django-pylibmc-bug Django CacheMiddleware has a multi-threading issue with pylibmc. CacheMiddleware shares a thread-unsafe cache object with many thre

Iuri de Silvio 1 Oct 19, 2022
Django app for building dashboards using raw SQL queries

django-sql-dashboard Django app for building dashboards using raw SQL queries Brings a useful subset of Datasette to Django. Currently only works with

Simon Willison 383 Jan 06, 2023
Yet another Django audit log app, hopefully the simplest one.

django-easy-audit Yet another Django audit log app, hopefully the easiest one. This app allows you to keep track of every action taken by your users.

Natán 510 Jan 02, 2023
Strawberry-django-plus - Enhanced Strawberry GraphQL integration with Django

strawberry-django-plus Enhanced Strawberry integration with Django. Built on top

BLB Ventures 138 Dec 28, 2022
Social Media Network Focuses On Data Security And Being Community Driven Web App

privalise Social Media Network Focuses On Data Security And Being Community Driven Web App The Main Idea: We`ve seen social media web apps that focuse

Privalise 8 Jun 25, 2021
A Django/Python web app that functions as a digital diary

My Django Diary Full-stack web application that functions as a digital diary using Django, Python, SQLite, HTML & CSS. Things I learned during this pr

1 Sep 30, 2022
Logan is a toolkit for building standalone Django applications

Logan Logan is a toolkit for running standalone Django applications. It provides you with tools to create a CLI runner, manage settings, and the abili

David Cramer 206 Jan 03, 2023
A test microblog project created using Django 4.0

django-microblog This is a test microblog project created using Django 4.0. But don't worry this is a fully working project. There is no super-amazing

Ali Kasimoglu 8 Jan 14, 2022
Let AngularJS play well with Django

django-angular Let Django play well with AngularJS What does it offer? Add AngularJS directives to Django Forms. This allows to handle client side for

Jacob Rief 1.2k Dec 27, 2022
A simple app that provides django integration for RQ (Redis Queue)

Django-RQ Django integration with RQ, a Redis based Python queuing library. Django-RQ is a simple app that allows you to configure your queues in djan

RQ 1.6k Jan 06, 2023
Tweak the form field rendering in templates, not in python-level form definitions. CSS classes and HTML attributes can be altered.

django-widget-tweaks Tweak the form field rendering in templates, not in python-level form definitions. Altering CSS classes and HTML attributes is su

Jazzband 1.8k Jan 02, 2023
Streamlining Django forms to provide all the wins of single-page-applications without the pain.

nango Streamlining Django forms to provide all the wins of single-page-applications without the pain. Key features Available to all Django deployments

Nick Farrell 107 Dec 12, 2022