cdent / wsgi-intercept

Intercept socket connection to wsgi applications for testing
MIT License
42 stars 21 forks source link

Missing 2 required positional arguments: 'environ' and 'start_response' with Django 2.2 #56

Open TheMatrix97 opened 5 years ago

TheMatrix97 commented 5 years ago

Hi! I'm trying to run my gabbits tests using wsgi-interceptor against a django 2.2 application Thats my load_tests function, where I import my django application in order to pass it to the interceptor


# For pathname munging
import os

# The module that build_tests comes from.
from gabbi import driver

from django_api.wsgi import application
# We need access to the WSGI application that hosts our service

# We're using fixtures in the YAML files, we need to know where to
# load them from.

# By convention the YAML files are put in a directory named
# "gabbits" that is in the same directory as the Python test file.
TESTS_DIR = 'gabbits'

def load_tests(loader, tests, pattern):
    """Provide a TestSuite to the discovery process."""
    test_dir = os.path.join(os.path.dirname(__file__), TESTS_DIR)
    # Pass "require_ssl=True" as an argument to force all tests
    # to use SSL in requests.
    return driver.build_tests(test_dir, loader,
                              intercept=application)

This is the contain of django_api/wsgi.py (which comes by default with django)

"""
WSGI config for django_api project.

It exposes the WSGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/1.9/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_api.settings")
application = get_wsgi_application()

When I run my gabbits tests using python -m testtools.run -v test/test_racotest.py I'm getting the following traceback for each test:

Traceback (most recent call last):
  File "/dades/python3/lib/python3.6/site-packages/gabbi/suitemaker.py", line 95, in do_test
    return test_method(*args, **kwargs)
  File "/dades/python3/lib/python3.6/site-packages/gabbi/case.py", line 94, in wrapper
    func(self)
  File "/dades/python3/lib/python3.6/site-packages/gabbi/case.py", line 148, in test_request
    self._run_test()
  File "/dades/python3/lib/python3.6/site-packages/gabbi/case.py", line 554, in _run_test
    redirect=test['redirects'])
  File "/dades/python3/lib/python3.6/site-packages/gabbi/case.py", line 463, in _run_request
    redirect=redirect
  File "/dades/python3/lib/python3.6/site-packages/gabbi/httpclient.py", line 44, in request
    method, absolute_uri, body=body, headers=headers, retries=retry)
  File "/dades/python3/lib/python3.6/site-packages/urllib3/request.py", line 68, in request
    **urlopen_kw)
  File "/dades/python3/lib/python3.6/site-packages/urllib3/request.py", line 89, in request_encode_url
    return self.urlopen(method, url, **extra_kw)
  File "/dades/python3/lib/python3.6/site-packages/urllib3/poolmanager.py", line 326, in urlopen
    response = conn.urlopen(method, u.request_uri, **kw)
  File "/dades/python3/lib/python3.6/site-packages/urllib3/connectionpool.py", line 603, in urlopen
    chunked=chunked)
  File "/dades/python3/lib/python3.6/site-packages/urllib3/connectionpool.py", line 355, in _make_request
    conn.request(method, url, **httplib_request_kw)
  File "/home/soft/python-3.6.4/lib/python3.6/http/client.py", line 1239, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/home/soft/python-3.6.4/lib/python3.6/http/client.py", line 1285, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/home/soft/python-3.6.4/lib/python3.6/http/client.py", line 1234, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/home/soft/python-3.6.4/lib/python3.6/http/client.py", line 1026, in _send_output
    self.send(msg)
  File "/home/soft/python-3.6.4/lib/python3.6/http/client.py", line 964, in send
    self.connect()
  File "/dades/python3/lib/python3.6/site-packages/wsgi_intercept/__init__.py", line 564, in connect
    (app, script_name) = self.get_app(self.host, self.port)
  File "/dades/python3/lib/python3.6/site-packages/wsgi_intercept/__init__.py", line 548, in get_app
    app = app_fn()
TypeError: __call__() missing 2 required positional arguments: 'environ' and 'start_response'

Does anyone have any idea of where is the error? Could it be a compatibility error between django wsgi default application and wsgi-intercept? Thank you in advance! :)

cdent commented 5 years ago
    return driver.build_tests(test_dir, loader,
                              intercept=application)

Try intercept=lambda: application and if that works, I'll try to improve the documentation appropriately. There used to be some magic in the guts of gabbi that tried to work around this, but it was too magic.

If that doesn't work let me know what the traceback is and I should be able to offer an alternative solution.

Whatever ends up working we can add to the docs in some fashion.

TheMatrix97 commented 5 years ago

Hey! It worked! :) Now I'm facing django problems xD I had to disable the ALLOWED_HOSTS as seems the interceptor puts a kind of random hostname: request: http://123c5eca-8d87-4ab1-8cdd-f9a2198023d5/test I'm only getting 404 errors from all requests, but seems wsgi-interceptor is working like charm!

cdent commented 5 years ago

seems the interceptor puts a kind of random hostname

Yeah, that's the combination of the gabbi and wsgi-intercept. You have to tell wsgi-intercept a host because it keeps a dict of intercept hosts to IOBytes that are doing the interceptinng. gabbi doesn't know or care what the host might be so it makes a uuid which works fine as long as nothing internally is caring about hostnames. If this is a limitation there are probably things we can do to gabbi to allow you to declare an intercepted host. I would think in this instance, though, it is probably easy to tell django you don't care abou that for the duration of the tests.

Any suggestions on how the docs should be improved?

TheMatrix97 commented 5 years ago

Actually this random hostname beahviour isn't a limitation, I just had to disable the allowed hosts check. I'm not a python expert, but maybe you could remark that the intercept param at build_test function (gabbi) expects a function, and you could provide it using lambda, in order to pass an anonymous one... Also you could mention this random hostname behaviour... Thank you for your work!