pytest-dev / pytest-dev/pytest-django

Error with Django internal when using pytest >= 4.2

Open
#710 21 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug needs-info
Dominant language
Python
Stars
1.5k
Forks
367
PR merge metrics
No merged PRs in 30d

Description

Hello,

Since I updated pytest to 4.2, I've got errors inside Django internals for some tests.
These tests worked fine with 4.1 and still work fine with Django embedded unittests.

Here the error:

______________________________________________________________________________ UserPageCheckTest.test_get_view_user_by_organisation _______________________________________________________________________________

self = <drop.front.tests.test_pages.UserPageCheckTest testMethod=test_get_view_user_by_organisation>, url = <URLPattern 'user/<int:pk>/' [name='view_user']>, pk_required = True, login_required = True

    def test_get_by_organisation(self, url=url, pk_required=pk_required, login_required=login_required):
>       base_url = self.get(url, pk_required, login_required)

drop/front/tests/test_pages.py:69: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
drop/front/tests/test_pages.py:49: in get
    self.client.force_login(self.user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:611: in force_login
    self._login(user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:624: in _login
    login(request, user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/__init__.py:132: in login
    user_logged_in.send(sender=user.__class__, request=request, user=user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in send
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in <listcomp>
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/models.py:20: in update_last_login
    user.save(update_fields=['last_login'])
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/base_user.py:73: in save
    super().save(*args, **kwargs)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:718: in save
    force_update=force_update, update_fields=update_fields)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:748: in save_base
    updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <User: admin>, raw = False, cls = <class 'drop.core.models.base.User'>, force_insert = False, force_update = False, using = 'default', update_fields = frozenset({'last_login'})

    def _save_table(self, raw=False, cls=None, force_insert=False,
                    force_update=False, using=None, update_fields=None):
        """
        Do the heavy-lifting involved in saving. Update or insert the data
        for a single table.
        """
        meta = cls._meta
        non_pks = [f for f in meta.local_concrete_fields if not f.primary_key]
    
        if update_fields:
            non_pks = [f for f in non_pks
                       if f.name in update_fields or f.attname in update_fields]
    
        pk_val = self._get_pk_val(meta)
        if pk_val is None:
            pk_val = meta.pk.get_pk_value_on_save(self)
            setattr(self, meta.pk.attname, pk_val)
        pk_set = pk_val is not None
        if not pk_set and (force_update or update_fields):
            raise ValueError("Cannot force an update in save() with no primary key.")
        updated = False
        # If possible, try an UPDATE. If that doesn't update anything, do an INSERT.
        if pk_set and not force_insert:
            base_qs = cls._base_manager.using(using)
            values = [(f, None, (getattr(self, f.attname) if raw else f.pre_save(self, False)))
                      for f in non_pks]
            forced_update = update_fields or force_update
            updated = self._do_update(base_qs, using, pk_val, values, update_fields,
                                      forced_update)
            if force_update and not updated:
                raise DatabaseError("Forced update did not affect any rows.")
            if update_fields and not updated:
>               raise DatabaseError("Save with update_fields did not affect any rows.")
E               django.db.utils.DatabaseError: Save with update_fields did not affect any rows.

../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:816: DatabaseError

As you can see, the error occurs when updating the last login date inside Django, but it happens only for few tests, which is very odd.

Here my current requirements:

Django==2.1.7
Pillow==5.4.1
pytest==4.3.1
pytest-cov==2.6.1
pytest-django==3.4.8
pytest-env==0.6.2

Thanks for any help or insight provided. ;)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the failure from drop/front/tests/test_pages.py, especially the tests that call self.client.force_login, using the listed Django and pytest versions. Compare behavior with pytest 4.1 and Django's embedded unittest runner, then trace the update_last_login failure through the Django paths shown in the traceback. Done means the affected tests run successfully under pytest >= 4.2 or the compatibility cause is clearly documented.

Written by the indexing model from the issue text.

Assessment

Tech stack
django, python
Domain
testing
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.