idlesign / pytest-djangoapp

Nice pytest plugin to help you with Django pluggable application testing.
https://github.com/idlesign/pytest-djangoapp
BSD 3-Clause "New" or "Revised" License
40 stars 6 forks source link

Django 4.0 test suite compatibility issues #23

Closed mcepl closed 1 year ago

mcepl commented 2 years ago

When running the test suite with Django-4.0 I get this error:

[   15s] _____________________________ test_request_client ______________________________
[   15s]
[   15s] request_client = <function request_client.<locals>.request_client_ at 0x7f278aefb040>
[   15s] user_create = <function user_create.<locals>.user_create_ at 0x7f278acac8b0>
[   15s]
[   15s]     def test_request_client(request_client, user_create):
[   15s]         client = request_client()
[   15s]         assert client
[   15s]         assert client.user is None
[   15s]         assert not client.user_logged_in
[   15s]
[   15s] >       response = client.get(('index', {'some_id': 10}))
[   15s]
[   15s] pytest_djangoapp/tests/test_fixtures_request.py:21:
[   15s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[   15s] /usr/lib/python3.9/site-packages/django/test/client.py:747: in get
[   15s]     response = super().get(path, data=data, secure=secure, **extra)
[   15s] /usr/lib/python3.9/site-packages/django/test/client.py:396: in get
[   15s]     return self.generic('GET', path, secure=secure, **{
[   15s] pytest_djangoapp/fixtures/request.py:44: in generic
[   15s]     path = reverse(path[0], kwargs=path[1])
[   15s] /usr/lib/python3.9/site-packages/django/urls/base.py:86: in reverse
[   15s]     return resolver._reverse_with_prefix(view, prefix, *args, **kwargs)
[   15s] /usr/lib/python3.9/site-packages/django/urls/resolvers.py:662: in _reverse_with_prefix
[   15s]     self._populate()
[   15s] /usr/lib/python3.9/site-packages/django/urls/resolvers.py:494: in _populate
[   15s]     for url_pattern in reversed(self.url_patterns):
[   15s] /usr/lib/python3.9/site-packages/django/utils/functional.py:48: in __get__
[   15s]     res = instance.__dict__[self.name] = self.func(instance)
[   15s] /usr/lib/python3.9/site-packages/django/urls/resolvers.py:632: in url_patterns
[   15s]     patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
[   15s] /usr/lib/python3.9/site-packages/django/utils/functional.py:48: in __get__
[   15s]     res = instance.__dict__[self.name] = self.func(instance)
[   15s] /usr/lib/python3.9/site-packages/django/urls/resolvers.py:625: in urlconf_module
[   15s]     return import_module(self.urlconf_name)
[   15s] /usr/lib64/python3.9/importlib/__init__.py:127: in import_module
[   15s]     return _bootstrap._gcd_import(name[level:], package, level)
[   15s] <frozen importlib._bootstrap>:1030: in _gcd_import
[   15s]     ???
[   15s] <frozen importlib._bootstrap>:1007: in _find_and_load
[   15s]     ???
[   15s] <frozen importlib._bootstrap>:986: in _find_and_load_unlocked
[   15s]     ???
[   15s] <frozen importlib._bootstrap>:680: in _load_unlocked
[   15s]     ???
[   15s] <frozen importlib._bootstrap_external>:850: in exec_module
[   15s]     ???
[   15s] <frozen importlib._bootstrap>:228: in _call_with_frames_removed
[   15s]     ???
[   15s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[   15s]
[   15s] >   from django.conf.urls import url
[   15s] E   ImportError: cannot import name 'url' from 'django.conf.urls' (/usr/lib/python3.9/site-packages/django/conf/urls/__init__.py)
[   15s]
[   15s] pytest_djangoapp/tests/testapp/urls.py:1: ImportError
[   15s] ---------------------------- Captured stderr setup -----------------------------
[   15s] Creating test database for alias 'default'...
[   15s] Creating test database for alias 'dummy'...
[   15s] --------------------------- Captured stderr teardown ---------------------------
[   15s] Destroying test database for alias 'default'...
[   15s] Destroying test database for alias 'dummy'...
[   15s] =========================== short test summary info ============================
[   15s] FAILED pytest_djangoapp/tests/test_fixtures_request.py::test_request_client
[   15s] =================== 1 failed, 19 passed, 1 skipped in 2.72s ====================

According to https://stackoverflow.com/a/70319607/164233 I have replaced the above import with from django.conf.urls import re_path as url, which is a brutal hack, but it seems to help.

Another problem was removed method is_ajax() of requests:

[    9s] _____________________________ test_request_client ______________________________
[    9s]
[    9s] request_client = <function request_client.<locals>.request_client_ at 0x7fbc8ddc9040>
[    9s] user_create = <function user_create.<locals>.user_create_ at 0x7fbc8db7a8b0>
[    9s]
[    9s]     def test_request_client(request_client, user_create):
[    9s]         client = request_client()
[    9s]         assert client
[    9s]         assert client.user is None
[    9s]         assert not client.user_logged_in
[    9s]
[    9s] >       response = client.get(('index', {'some_id': 10}))
[    9s]
[    9s] pytest_djangoapp/tests/test_fixtures_request.py:21:
[    9s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[    9s] /usr/lib/python3.9/site-packages/django/test/client.py:747: in get
[    9s]     response = super().get(path, data=data, secure=secure, **extra)
[    9s] /usr/lib/python3.9/site-packages/django/test/client.py:396: in get
[    9s]     return self.generic('GET', path, secure=secure, **{
[    9s] pytest_djangoapp/fixtures/request.py:46: in generic
[    9s]     return super(DjangoappRequestFactory, self).generic(method, path, *args, **kwargs)
[    9s] /usr/lib/python3.9/site-packages/django/test/client.py:473: in generic
[    9s]     return self.request(**r)
[    9s] /usr/lib/python3.9/site-packages/django/test/client.py:721: in request
[    9s]     self.check_exception(response)
[    9s] /usr/lib/python3.9/site-packages/django/test/client.py:582: in check_exception
[    9s]     raise exc_value
[    9s] /usr/lib/python3.9/site-packages/django/core/handlers/exception.py:47: in inner
[    9s]     response = get_response(request)
[    9s] /usr/lib/python3.9/site-packages/django/core/handlers/base.py:181: in _get_response
[    9s]     response = wrapped_callback(request, *callback_args, **callback_kwargs)
[    9s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[    9s]
[    9s] request = <WSGIRequest: GET '/index/10/'>, some_id = '10'
[    9s]
[    9s]     def index(request, some_id):
[    9s]
[    9s]         if request.method == 'POST':
[    9s]             return HttpResponse('json')
[    9s]
[    9s] >       if request.is_ajax():
[    9s] E       AttributeError: 'WSGIRequest' object has no attribute 'is_ajax'
[    9s]
[    9s] pytest_djangoapp/tests/testapp/urls.py:16: AttributeError
[    9s] ---------------------------- Captured stderr setup -----------------------------
[    9s] Creating test database for alias 'default'...
[    9s] Creating test database for alias 'dummy'...
[    9s] ------------------------------ Captured log call -------------------------------
[    9s] ERROR    django.request:log.py:225 Internal Server Error: /index/10/
[    9s] Traceback (most recent call last):
[    9s]   File "/usr/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
[    9s]     response = get_response(request)
[    9s]   File "/usr/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
[    9s]     response = wrapped_callback(request, *callback_args, **callback_kwargs)
[    9s]   File "/home/abuild/rpmbuild/BUILD/pytest-djangoapp-0.15.2/pytest_djangoapp/tests/testapp/urls.py", line 16, in index
[    9s]     if request.is_ajax():
[    9s] AttributeError: 'WSGIRequest' object has no attribute 'is_ajax'

Following the documentation I have created another brutal hack and the resulting patch which makes the test suite pass is:

---
 pytest_djangoapp/tests/testapp/urls.py |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

--- a/pytest_djangoapp/tests/testapp/urls.py
+++ b/pytest_djangoapp/tests/testapp/urls.py
@@ -1,4 +1,4 @@
-from django.conf.urls import url
+from django.urls import re_path as url
 from django.http import HttpResponse

 from pytest_djangoapp.compat import get_urlpatterns
@@ -7,13 +7,15 @@ from pytest_djangoapp.compat import get_
 def raise_exception(request):
     raise Exception('This one should be handled by 500 technical view')

+def is_ajax(req):
+    return req.headers.get('x-requested-with') == 'XMLHttpRequest'

 def index(request, some_id):

     if request.method == 'POST':
         return HttpResponse('json')

-    if request.is_ajax():
+    if is_ajax(request):
         return HttpResponse('ajaxed')

     from django.templatetags.static import static
idlesign commented 2 years ago

Thank you.

But that fix has been in master for some time already.

https://github.com/idlesign/pytest-djangoapp/blob/master/pytest_djangoapp/tests/testapp/urls.py

Please give it a try.

mcepl commented 2 years ago

Well, make a release.

idlesign commented 2 years ago

There are no changes in plugin itself, only in test suite, nothing to release yet.

mcepl commented 2 years ago

Right, that’s true.