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)
Dynamic Django settings.

Constance - Dynamic Django settings A Django app for storing dynamic settings in pluggable backends (Redis and Django model backend built in) with an

Jazzband 1.5k Jan 07, 2023
Py-instant-search-redis - Source code example for how to build an instant search with redis in python

py-instant-search-redis Source code example for how to build an instant search (

Giap Le 4 Feb 17, 2022
Twitter Bootstrap for Django Form

Django bootstrap form Twitter Bootstrap for Django Form. A simple Django template tag to work with Bootstrap Installation Install django-bootstrap-for

tzangms 557 Oct 19, 2022
Учебное пособие по основам Django и сопутствующим технологиям

Учебный проект для закрепления основ Django Подробный разбор проекта здесь. Инструкция по запуску проекта на своей машине: Скачиваем репозиторий Устан

Stanislav Garanzha 12 Dec 30, 2022
pdm-django: Django command shortcuts for PDM

pdm-django: Django command shortcuts for PDM A plugin that gives you command shortcuts for developing with PDM. pdm run python manage.py runserver -

Neutron Sync 2 Aug 11, 2022
Developer-friendly asynchrony for Django

Django Channels Channels augments Django to bring WebSocket, long-poll HTTP, task offloading and other async support to your code, using familiar Djan

Django 5.5k Jan 06, 2023
Use webpack to generate your static bundles without django's staticfiles or opaque wrappers.

django-webpack-loader Use webpack to generate your static bundles without django's staticfiles or opaque wrappers. Django webpack loader consumes the

2.4k Dec 24, 2022
🔥 Campus-Run Django Server🔥

🏫 Campus-Run Campus-Run is a 3D racing game set on a college campus. Designed this service to comfort university students who are unable to visit the

Youngkwon Kim 1 Feb 08, 2022
simple project management tool for educational purposes

Taskcamp This software is used for educational and demonstrative purposes. It's a simple project management tool powered by Django Framework Install B

Ilia Dmitriev 6 Nov 08, 2022
Django Simple Spam Blocker is blocking spam by regular expression.

Django Simple Spam Blocker is blocking spam by regular expression.

Masahiko Okada 23 Nov 29, 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
Comparing Database performance with Django ORM

Comparing Database performance with Django ORM Postgresql MySQL MariaDB SQLite Comparing database operation performance using django ORM. PostgreSQL v

Sarath ak 21 Nov 14, 2022
Meta package to combine turbo-django and stimulus-django

Hotwire + Django This repository aims to help you integrate Hotwire with Django 🚀 Inspiration might be taken from @hotwired/hotwire-rails. We are sti

Hotwire for Django 31 Aug 09, 2022
Auto-detecting the n+1 queries problem in Python

nplusone nplusone is a library for detecting the n+1 queries problem in Python ORMs, including SQLAlchemy, Peewee, and the Django ORM. The Problem Man

Joshua Carp 837 Dec 29, 2022
Chatbot for ordering and tracking a Pizza.

Pizza Chatbot To start the app, follow the below steps: Clone the repo using the below command: git clone Shreya Shah 1 Jul 15, 2021

Use minify-html, the extremely fast HTML + JS + CSS minifier, with Django.

django-minify-html Use minify-html, the extremely fast HTML + JS + CSS minifier, with Django. Requirements Python 3.8 to 3.10 supported. Django 2.2 to

Adam Johnson 60 Dec 28, 2022
django-quill-editor makes Quill.js easy to use on Django Forms and admin sites

django-quill-editor django-quill-editor makes Quill.js easy to use on Django Forms and admin sites No configuration required for static files! The ent

lhy 139 Dec 05, 2022
A Django web application that allows you to be in the loop about everything happening in your neighborhood.

A Django web application that allows you to be in the loop about everything happening in your neighborhood. From contact information of different handyman to meeting announcements or even alerts.

Kennedy Ngugi Mwaura 3 Dec 11, 2022
GameStop clone with Django

GameStop clone with Django This is my side project with GameStop clone Author: HackerApe GitHub Profile: View Profile LinkedIn Profile: View Profile

Dmitriy Shin 2 Dec 26, 2021
This is django-import-export module that exports data into many formats

django-import-export This is django-import-export module which exports data into many formats, you can implement this in your admin panel. - Dehydrat

Shivam Rohilla 3 Jun 03, 2021